Compare commits

...

63 Commits
1.2.1 ... 1.3.3

Author SHA1 Message Date
John Rommel Estropia
05b4a7092a updated podspec for OSX 2015-10-30 01:46:47 +09:00
John Rommel Estropia
6aed070e7c version bump for OSX support 2015-10-30 01:36:15 +09:00
John Estropia
fcb1d7cbbc OSX support!!!11 2015-10-29 17:00:10 +09:00
John Estropia
d074aad111 Merge branch 'master' into develop 2015-10-26 14:42:31 +09:00
John Estropia
b7685dc747 allow Sequences of NSManagedObject subclasses as argument to delete() method 2015-10-26 14:41:58 +09:00
John Rommel Estropia
a185bc96c0 updated README 2015-10-24 11:41:13 +09:00
John Rommel Estropia
91aef44803 fix pod dependency 2015-10-23 00:49:34 +09:00
John Rommel Estropia
dcfb09eda7 attempt sight improvement for the FRC bug workaround #20 2015-10-23 00:40:38 +09:00
John Estropia
9ca83d9c5d watchOS support (fixes #19) 2015-10-20 21:01:10 +09:00
John Estropia
b00eaf2d0b fix warnings on watchOS 2015-10-20 20:54:09 +09:00
John Estropia
dc8bdf3bad watch OS support 2015-10-20 20:38:58 +09:00
John Estropia
4792c4462e fix section index titles when refetching a listMonitor 2015-10-15 18:29:08 +09:00
John Estropia
524757a7cf just a safety measure for the rare case that the FRC delegate gets released earlier than the FRC 2015-10-13 10:47:48 +09:00
John Rommel Estropia
0b6298a802 tidy up 2015-10-07 00:57:48 +09:00
John Estropia
ae77558ae8 Merge pull request #16 from mac-cain13/patch-1
Fix FRCdelegate issue where invalid type is passed
2015-10-07 00:44:15 +09:00
Mathijs Kadijk
d33aa9c5cf Fix FRCdelegate issue where invalid type is passed
See also https://forums.developer.apple.com/thread/12184#31850
2015-10-06 15:30:22 +02:00
John Estropia
d89319d324 Workaround for Xcode 7.0.1+iOS 9 FRC bug 2015-09-30 11:41:27 +09:00
John Estropia
cf9af6eef5 Merge branch 'develop' 2015-09-28 20:46:14 +09:00
John Estropia
b9ec66f425 fix entityNameMapping bug 2015-09-28 20:44:19 +09:00
John Estropia
2a8df0596d Update README.md 2015-09-24 23:47:06 +09:00
John Rommel Estropia
83e6a41d88 Merge branch 'master' into develop 2015-09-22 11:40:28 +09:00
John Rommel Estropia
c6fe494fe1 updated podspec dependency 2015-09-21 23:30:41 +09:00
John Rommel Estropia
7771e047e2 updated GCDKit version to remove warnings 2015-09-21 23:23:22 +09:00
John Rommel Estropia
5b0439835b Deprecated DetachedDataTransaction in favor of UnsafeDataTransaction. beginDetached() methods are also deprecated; use beginUnsafe() instead. 2015-09-21 15:08:46 +09:00
John Rommel Estropia
622c5aa652 Tighter generics implementations. You can now pass any SequenceType's for methods that previously only accepts Array's. 2015-09-19 19:45:01 +09:00
John Rommel Estropia
114b7ce605 Tighter generics implementations. You can now pass any SequenceType's for methods that previously only accepts Array's. 2015-09-19 18:20:52 +09:00
John Rommel Estropia
7451fbe026 added README sections about ImportableObject and ImportableUniqueObject, as well as the new fetchExisting() method usage 2015-09-19 16:23:59 +09:00
John Rommel Estropia
ee2398fcdf updated readme 2015-09-18 07:14:41 +09:00
John Rommel Estropia
8d26501040 WIP: Readme 2015-09-14 07:44:23 +09:00
John Estropia
0709fe95cf use transaction queue for refetching instead of a global queue 2015-09-11 15:06:36 +09:00
John Estropia
656a99fe12 added thread safety checks to ListMonitor to prevent deadlocks after calling refetch() 2015-09-11 13:59:28 +09:00
John Estropia
726e0eabe9 dispatch_group seems more semantically fitting than semaphore 2015-09-11 13:50:29 +09:00
John Estropia
032764b9b7 tidy up 2015-09-10 16:59:55 +09:00
John Estropia
5461bb0736 workaround an NSFetchedResultsController bug in Xcode 7 targeted on iOS 8 devices where errant index paths cause crashes 2015-09-10 16:57:35 +09:00
John Estropia
4c6bc4f494 completed appledocs for importing methods 2015-09-10 13:28:53 +09:00
John Rommel Estropia
63a43a6487 WIP: documentation 2015-09-10 07:21:53 +09:00
John Estropia
6a006d5d7c added a flag to inspect the current state of a refetch 2015-09-08 18:12:52 +09:00
John Estropia
399517e357 ListMonitor is now refetch-able. Implement the listMonitorWillRefetch and listMonitorDidRefetch methods of ListObserver and call the refetch(...) method of ListMonitor 2015-09-08 17:21:15 +09:00
John Estropia
f47adc12b3 fix typealias name clash when observing both ListMonitor and ObjectMonitor 2015-09-02 13:44:37 +09:00
John Estropia
0de1733efe oops 2015-09-01 21:05:59 +09:00
John Estropia
e627cf8161 test improvements to ListMonitor 2015-09-01 20:08:45 +09:00
John Rommel Estropia
22943d2c76 added warn_unused_result annotations where they seem reasonable 2015-08-29 22:29:03 +09:00
John Estropia
56ea14d53c fix disconnected observers when an observer registers itself to multiple ListMonitors 2015-08-28 12:09:55 +09:00
John Rommel Estropia
21a524d725 tidy up 2015-08-28 08:09:06 +09:00
John Estropia
d5e769be6c turns out inout arguments in closures are malloc nightmares. this finally fixes it 2015-08-27 22:24:40 +09:00
John Estropia
ea6b6f2c37 bandaid solution for over-deallocated sequences bug in swift (for now) 2015-08-27 19:06:52 +09:00
John Estropia
c3ef8a4172 bug fix for dictionaries getting deallocated earlier 2015-08-27 17:28:40 +09:00
John Rommel Estropia
16aabe1f3b optimize fetching objects with NSManagedObjectIDs 2015-08-26 23:59:18 +09:00
John Estropia
10e0cf8d2c tidy up 2015-08-25 20:33:36 +09:00
John Estropia
3a0f53321a improved behavior for #12 (as of Xcode 7 beta 6) 2015-08-25 14:35:22 +09:00
John Estropia
0da43d5132 Merge branch 'develop' of https://github.com/JohnEstropia/CoreStore into develop 2015-08-25 14:27:32 +09:00
John Estropia
69f902ef20 XCode7 beta 6 updates 2015-08-25 14:24:18 +09:00
John Estropia
d04b4ca085 added utility for ListMonitor to return the index/indexPath of a specified object 2015-08-24 20:40:19 +09:00
John Estropia
8ed6a78609 CoreStore adapter method 2015-08-24 17:36:40 +09:00
John Estropia
0c9e6afe0e added utility to inspect NSEntityDescription for a given NSManagedObject type 2015-08-24 17:33:27 +09:00
John Rommel Estropia
ff4629908a Merge branch 'develop' of github.com:JohnEstropia/CoreStore into develop 2015-08-23 14:37:34 +09:00
John Rommel Estropia
d3ffe7a8fc add default implementation for souldUpdateFromImportSource 2015-08-23 14:37:21 +09:00
John Rommel Estropia
3919ada428 Merge branch 'master' into develop 2015-08-23 14:29:44 +09:00
John Rommel Estropia
006d5e1402 rewrote ImportableObject protocol methods 2015-08-23 14:15:48 +09:00
John Rommel Estropia
093c1d410f temporarily fix an Xcode 7 bug (still present as of beta 5) (temporarily fixes #12) 2015-08-23 14:02:27 +09:00
John Estropia
7555ff3ad0 allow preprocessing dictionary mapping before importing objects 2015-08-21 19:48:47 +09:00
John Estropia
4c16a961ba added default implementation to didInsertFromImportSource 2015-08-21 18:28:02 +09:00
John Estropia
1121d44d7b pass transaction to ImportableObject methods 2015-08-21 18:19:21 +09:00
56 changed files with 2696 additions and 893 deletions

View File

@@ -1,16 +1,19 @@
Pod::Spec.new do |s|
s.name = "CoreStore"
s.version = "1.2.1"
s.version = "1.3.3"
s.license = "MIT"
s.summary = "Simple, elegant, and smart Core Data programming with 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.author = { "John Rommel Estropia" => "rommel.estropia@gmail.com" }
s.source = { :git => "https://github.com/JohnEstropia/CoreStore.git", :tag => s.version.to_s }
s.ios.deployment_target = "8.0"
s.osx.deployment_target = "10.10"
s.watchos.deployment_target = "2.0"
s.source_files = "CoreStore", "CoreStore/**/*.{swift}"
s.frameworks = "Foundation", "UIKit", "CoreData"
s.osx.exclude_files = "CoreStore/Observing/*.{swift}", "CoreStore/Internal/FetchedResultsControllerDelegate.swift"
s.frameworks = "Foundation", "CoreData"
s.requires_arc = true
s.dependency "GCDKit", "1.1.1"
s.dependency "GCDKit", "1.1.3"
end

View File

@@ -13,9 +13,127 @@
2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F291E2619C6D3CF007AF63F /* CoreStore.swift */; };
B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */; };
B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; };
B52DD17E1BE1F8CD00949AFE /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52DD1741BE1F8CC00949AFE /* CoreStore.framework */; };
B52DD1901BE1F8E600949AFE /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5D808021A34715700A44484 /* GCDKit.framework */; };
B52DD1911BE1F8EB00949AFE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5548CD51BD65AE00077652A /* Foundation.framework */; };
B52DD1921BE1F8F000949AFE /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5548CD71BD65AE50077652A /* CoreData.framework */; };
B52DD1931BE1F8FD00949AFE /* CoreStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F03A53519C5C6DA005002A5 /* CoreStore.h */; settings = {ATTRIBUTES = (Public, ); }; };
B52DD1941BE1F92500949AFE /* CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F291E2619C6D3CF007AF63F /* CoreStore.swift */; };
B52DD1951BE1F92500949AFE /* NSError+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* NSError+CoreStore.swift */; };
B52DD1961BE1F92500949AFE /* DataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EDB1AFF84500064E85B /* DataStack.swift */; };
B52DD1971BE1F92500949AFE /* PersistentStoreResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EDE1AFF84500064E85B /* PersistentStoreResult.swift */; };
B52DD1981BE1F92500949AFE /* CoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */; };
B52DD1991BE1F92800949AFE /* DefaultLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EE31AFF84610064E85B /* DefaultLogger.swift */; };
B52DD19A1BE1F92800949AFE /* CoreStore+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EE41AFF84610064E85B /* CoreStore+Logging.swift */; };
B52DD19B1BE1F92800949AFE /* CoreStoreLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EE51AFF84610064E85B /* CoreStoreLogger.swift */; };
B52DD19C1BE1F92C00949AFE /* Into.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007101B3F6BD500A9A8F9 /* Into.swift */; };
B52DD19D1BE1F92C00949AFE /* BaseDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEB1AFF846E0064E85B /* BaseDataTransaction.swift */; };
B52DD19E1BE1F92C00949AFE /* AsynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEA1AFF846E0064E85B /* AsynchronousDataTransaction.swift */; };
B52DD19F1BE1F92C00949AFE /* SynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EF31AFF846E0064E85B /* SynchronousDataTransaction.swift */; };
B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EED1AFF846E0064E85B /* UnsafeDataTransaction.swift */; };
B52DD1A11BE1F92C00949AFE /* DataStack+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEC1AFF846E0064E85B /* DataStack+Transaction.swift */; };
B52DD1A21BE1F92C00949AFE /* CoreStore+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEE1AFF846E0064E85B /* CoreStore+Transaction.swift */; };
B52DD1A31BE1F92C00949AFE /* SaveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EF21AFF846E0064E85B /* SaveResult.swift */; };
B52DD1A41BE1F92F00949AFE /* ImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */; };
B52DD1A51BE1F92F00949AFE /* ImportableUniqueObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */; };
B52DD1A61BE1F92F00949AFE /* BaseDataTransaction+Importing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */; };
B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EFE1AFF847B0064E85B /* BaseDataTransaction+Querying.swift */; };
B52DD1A81BE1F93200949AFE /* DataStack+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F061AFF847B0064E85B /* DataStack+Querying.swift */; };
B52DD1A91BE1F93200949AFE /* CoreStore+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F071AFF847B0064E85B /* CoreStore+Querying.swift */; };
B52DD1AA1BE1F93500949AFE /* ClauseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */; };
B52DD1AB1BE1F93900949AFE /* From.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F011AFF847B0064E85B /* From.swift */; };
B52DD1AC1BE1F93900949AFE /* Select.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F031AFF847B0064E85B /* Select.swift */; };
B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F051AFF847B0064E85B /* Where.swift */; };
B52DD1AE1BE1F93900949AFE /* OrderBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F041AFF847B0064E85B /* OrderBy.swift */; };
B52DD1AF1BE1F93900949AFE /* GroupBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F021AFF847B0064E85B /* GroupBy.swift */; };
B52DD1B01BE1F93900949AFE /* Tweak.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F001AFF847B0064E85B /* Tweak.swift */; };
B52DD1B81BE1F94000949AFE /* DataStack+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */; };
B52DD1B91BE1F94000949AFE /* CoreStore+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */; };
B52DD1BA1BE1F94000949AFE /* MigrationChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007151B4018AB00A9A8F9 /* MigrationChain.swift */; };
B52DD1BB1BE1F94000949AFE /* MigrationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A261201B64BFDB006EB6D3 /* MigrationType.swift */; };
B52DD1BC1BE1F94000949AFE /* MigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965231B356B820075EE4A /* MigrationResult.swift */; };
B52DD1BD1BE1F94300949AFE /* NSManagedObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F271AFF84920064E85B /* NSManagedObject+Convenience.swift */; };
B52DD1BE1BE1F94300949AFE /* NSProgress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */; };
B52DD1BF1BE1F94600949AFE /* AssociatedObjects.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2A1AFF849C0064E85B /* AssociatedObjects.swift */; };
B52DD1C11BE1F94600949AFE /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834BA1B7691F3001D3D50 /* Functions.swift */; };
B52DD1C21BE1F94600949AFE /* MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AB1B51285300714891 /* MigrationManager.swift */; };
B52DD1C31BE1F94600949AFE /* NotificationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */; };
B52DD1C41BE1F94600949AFE /* NSFileManager+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59D5C211B5BA34B00453479 /* NSFileManager+Setup.swift */; };
B52DD1C51BE1F94600949AFE /* NSManagedObject+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */; };
B52DD1C61BE1F94600949AFE /* NSManagedObjectContext+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */; };
B52DD1C71BE1F94600949AFE /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; };
B52DD1C81BE1F94600949AFE /* NSManagedObjectContext+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */; };
B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; };
B52DD1CA1BE1F94600949AFE /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; };
B52DD1CB1BE1F94600949AFE /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; };
B52DD1CC1BE1F94D00949AFE /* CoreStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F03A53F19C5C6DA005002A5 /* CoreStoreTests.swift */; };
B52DD1CD1BE1F94D00949AFE /* TestEntity1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D372851A39CDDB00F583D9 /* TestEntity1.swift */; };
B52DD1CE1BE1F94D00949AFE /* TestEntity2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D5E0CE1A4D6AAB006468AF /* TestEntity2.swift */; };
B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */; };
B5598BCC1BE2093D0092EFCE /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; };
B56007111B3F6BD500A9A8F9 /* Into.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007101B3F6BD500A9A8F9 /* Into.swift */; };
B56007141B3F6C2800A9A8F9 /* SectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007131B3F6C2800A9A8F9 /* SectionBy.swift */; };
B56007161B4018AB00A9A8F9 /* MigrationChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007151B4018AB00A9A8F9 /* MigrationChain.swift */; };
B563217A1BD650DE006C9394 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56321791BD650DE006C9394 /* CoreData.framework */; };
B563217C1BD650E3006C9394 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B563217B1BD650E3006C9394 /* Foundation.framework */; };
B563217D1BD650FA006C9394 /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56321691BD64F99006C9394 /* GCDKit.framework */; };
B563217E1BD65110006C9394 /* CoreStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F03A53519C5C6DA005002A5 /* CoreStore.h */; settings = {ATTRIBUTES = (Public, ); }; };
B563217F1BD65216006C9394 /* CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F291E2619C6D3CF007AF63F /* CoreStore.swift */; };
B56321801BD65216006C9394 /* NSError+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* NSError+CoreStore.swift */; };
B56321811BD65216006C9394 /* DataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EDB1AFF84500064E85B /* DataStack.swift */; };
B56321821BD65216006C9394 /* PersistentStoreResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EDE1AFF84500064E85B /* PersistentStoreResult.swift */; };
B56321831BD65216006C9394 /* CoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */; };
B56321841BD65216006C9394 /* DefaultLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EE31AFF84610064E85B /* DefaultLogger.swift */; };
B56321851BD65216006C9394 /* CoreStore+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EE41AFF84610064E85B /* CoreStore+Logging.swift */; };
B56321861BD65216006C9394 /* CoreStoreLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EE51AFF84610064E85B /* CoreStoreLogger.swift */; };
B56321871BD65216006C9394 /* Into.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007101B3F6BD500A9A8F9 /* Into.swift */; };
B56321881BD65216006C9394 /* BaseDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEB1AFF846E0064E85B /* BaseDataTransaction.swift */; };
B56321891BD65216006C9394 /* AsynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEA1AFF846E0064E85B /* AsynchronousDataTransaction.swift */; };
B563218A1BD65216006C9394 /* SynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EF31AFF846E0064E85B /* SynchronousDataTransaction.swift */; };
B563218B1BD65216006C9394 /* UnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EED1AFF846E0064E85B /* UnsafeDataTransaction.swift */; };
B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEC1AFF846E0064E85B /* DataStack+Transaction.swift */; };
B563218D1BD65216006C9394 /* CoreStore+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEE1AFF846E0064E85B /* CoreStore+Transaction.swift */; };
B563218E1BD65216006C9394 /* SaveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EF21AFF846E0064E85B /* SaveResult.swift */; };
B563218F1BD65216006C9394 /* ImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */; };
B56321901BD65216006C9394 /* ImportableUniqueObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */; };
B56321911BD65216006C9394 /* BaseDataTransaction+Importing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */; };
B56321921BD65216006C9394 /* BaseDataTransaction+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EFE1AFF847B0064E85B /* BaseDataTransaction+Querying.swift */; };
B56321931BD65216006C9394 /* DataStack+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F061AFF847B0064E85B /* DataStack+Querying.swift */; };
B56321941BD65216006C9394 /* CoreStore+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F071AFF847B0064E85B /* CoreStore+Querying.swift */; };
B56321951BD65216006C9394 /* ClauseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */; };
B56321961BD65216006C9394 /* From.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F011AFF847B0064E85B /* From.swift */; };
B56321971BD65216006C9394 /* Select.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F031AFF847B0064E85B /* Select.swift */; };
B56321981BD65216006C9394 /* Where.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F051AFF847B0064E85B /* Where.swift */; };
B56321991BD65216006C9394 /* OrderBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F041AFF847B0064E85B /* OrderBy.swift */; };
B563219A1BD65216006C9394 /* GroupBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F021AFF847B0064E85B /* GroupBy.swift */; };
B563219B1BD65216006C9394 /* Tweak.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F001AFF847B0064E85B /* Tweak.swift */; };
B563219C1BD65216006C9394 /* SectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007131B3F6C2800A9A8F9 /* SectionBy.swift */; };
B563219D1BD65216006C9394 /* DataStack+Observing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F1A1AFF84860064E85B /* DataStack+Observing.swift */; };
B563219E1BD65216006C9394 /* CoreStore+Observing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F1B1AFF84860064E85B /* CoreStore+Observing.swift */; };
B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F1C1AFF84860064E85B /* ObjectMonitor.swift */; };
B56321A01BD65216006C9394 /* ObjectObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F1F1AFF84860064E85B /* ObjectObserver.swift */; };
B56321A11BD65216006C9394 /* ListMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F1D1AFF84860064E85B /* ListMonitor.swift */; };
B56321A21BD65216006C9394 /* ListObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F1E1AFF84860064E85B /* ListObserver.swift */; };
B56321A31BD65216006C9394 /* DataStack+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */; };
B56321A41BD65216006C9394 /* CoreStore+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */; };
B56321A51BD65216006C9394 /* MigrationChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56007151B4018AB00A9A8F9 /* MigrationChain.swift */; };
B56321A61BD65216006C9394 /* MigrationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A261201B64BFDB006EB6D3 /* MigrationType.swift */; };
B56321A71BD65216006C9394 /* MigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965231B356B820075EE4A /* MigrationResult.swift */; };
B56321A81BD65219006C9394 /* NSManagedObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F271AFF84920064E85B /* NSManagedObject+Convenience.swift */; };
B56321A91BD65219006C9394 /* NSProgress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */; };
B56321AA1BD6521C006C9394 /* AssociatedObjects.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2A1AFF849C0064E85B /* AssociatedObjects.swift */; };
B56321AB1BD6521C006C9394 /* FetchedResultsControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */; };
B56321AC1BD6521C006C9394 /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834BA1B7691F3001D3D50 /* Functions.swift */; };
B56321AD1BD6521C006C9394 /* MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AB1B51285300714891 /* MigrationManager.swift */; };
B56321AE1BD6521C006C9394 /* NotificationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */; };
B56321AF1BD6521C006C9394 /* NSFileManager+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59D5C211B5BA34B00453479 /* NSFileManager+Setup.swift */; };
B56321B01BD6521C006C9394 /* NSManagedObject+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */; };
B56321B11BD6521C006C9394 /* NSManagedObjectContext+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */; };
B56321B21BD6521C006C9394 /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; };
B56321B31BD6521C006C9394 /* NSManagedObjectContext+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */; };
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; };
B56321B51BD6521C006C9394 /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; };
B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; };
B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */; };
B56965241B356B820075EE4A /* MigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965231B356B820075EE4A /* MigrationResult.swift */; };
B59D5C221B5BA34B00453479 /* NSFileManager+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59D5C211B5BA34B00453479 /* NSFileManager+Setup.swift */; };
@@ -24,7 +142,6 @@
B5D372841A39CD6900F583D9 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; };
B5D372861A39CDDB00F583D9 /* TestEntity1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D372851A39CDDB00F583D9 /* TestEntity1.swift */; };
B5D39A0219FD00C9000E91BB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5D39A0119FD00C9000E91BB /* Foundation.framework */; };
B5D39A0419FD00DE000E91BB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5D39A0319FD00DE000E91BB /* UIKit.framework */; };
B5D5E0CF1A4D6AAB006468AF /* TestEntity2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D5E0CE1A4D6AAB006468AF /* TestEntity2.swift */; };
B5D8080E1A3471A500A44484 /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5D808021A34715700A44484 /* GCDKit.framework */; };
B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */; };
@@ -37,7 +154,7 @@
B5E84EF41AFF846E0064E85B /* AsynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEA1AFF846E0064E85B /* AsynchronousDataTransaction.swift */; };
B5E84EF51AFF846E0064E85B /* BaseDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEB1AFF846E0064E85B /* BaseDataTransaction.swift */; };
B5E84EF61AFF846E0064E85B /* DataStack+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEC1AFF846E0064E85B /* DataStack+Transaction.swift */; };
B5E84EF71AFF846E0064E85B /* DetachedDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EED1AFF846E0064E85B /* DetachedDataTransaction.swift */; };
B5E84EF71AFF846E0064E85B /* UnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EED1AFF846E0064E85B /* UnsafeDataTransaction.swift */; };
B5E84EF81AFF846E0064E85B /* CoreStore+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EEE1AFF846E0064E85B /* CoreStore+Transaction.swift */; };
B5E84EFB1AFF846E0064E85B /* SaveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EF21AFF846E0064E85B /* SaveResult.swift */; };
B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EF31AFF846E0064E85B /* SynchronousDataTransaction.swift */; };
@@ -66,12 +183,56 @@
B5E84F381AFF85470064E85B /* NSManagedObject+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */; };
B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */; };
B5E84F411AFF8CCD0064E85B /* ClauseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */; };
B5F1DA8D1B9AA97D007C5CBB /* ImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */; };
B5F1DA901B9AA991007C5CBB /* ImportableUniqueObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */; };
B5FAD6A91B50A4B400714891 /* NSProgress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */; };
B5FAD6AC1B51285300714891 /* MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AB1B51285300714891 /* MigrationManager.swift */; };
B5FAD6AE1B518DCB00714891 /* CoreStore+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
B52DD17F1BE1F8CD00949AFE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 2F03A52719C5C6DA005002A5 /* Project object */;
proxyType = 1;
remoteGlobalIDString = B52DD1731BE1F8CC00949AFE;
remoteInfo = "CoreStore OSX";
};
B52DD18E1BE1F8DC00949AFE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B5D806C51A34715700A44484 /* GCDKit.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = B563212A1BD6359A006C9394;
remoteInfo = "GCDKit OSX";
};
B56321641BD64F99006C9394 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B5D806C51A34715700A44484 /* GCDKit.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = B563212B1BD6359A006C9394;
remoteInfo = "GCDKit OSX";
};
B56321661BD64F99006C9394 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B5D806C51A34715700A44484 /* GCDKit.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = B56321401BD63D14006C9394;
remoteInfo = "GCDKitTests OSX";
};
B56321681BD64F99006C9394 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B5D806C51A34715700A44484 /* GCDKit.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = B56321501BD6408F006C9394;
remoteInfo = "GCDKit watchOS";
};
B56321771BD650A3006C9394 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B5D806C51A34715700A44484 /* GCDKit.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = B563214F1BD6408F006C9394;
remoteInfo = "GCDKit watchOS";
};
B5D372871A39CF4D00F583D9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 2F03A52719C5C6DA005002A5 /* Project object */;
@@ -113,9 +274,17 @@
2F291E2619C6D3CF007AF63F /* CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoreStore.swift; sourceTree = "<group>"; };
B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Setup.swift"; sourceTree = "<group>"; };
B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectModel+Setup.swift"; sourceTree = "<group>"; };
B52DD1741BE1F8CC00949AFE /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchedResultsControllerDelegate.swift; sourceTree = "<group>"; };
B5548CD51BD65AE00077652A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
B5548CD71BD65AE50077652A /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; };
B56007101B3F6BD500A9A8F9 /* Into.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Into.swift; sourceTree = "<group>"; };
B56007131B3F6C2800A9A8F9 /* SectionBy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionBy.swift; sourceTree = "<group>"; };
B56007151B4018AB00A9A8F9 /* MigrationChain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationChain.swift; sourceTree = "<group>"; };
B563216F1BD65082006C9394 /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B56321791BD650DE006C9394 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS2.0.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; };
B563217B1BD650E3006C9394 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS2.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DataStack+Migration.swift"; sourceTree = "<group>"; };
B56965231B356B820075EE4A /* MigrationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationResult.swift; sourceTree = "<group>"; };
B59D5C211B5BA34B00453479 /* NSFileManager+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFileManager+Setup.swift"; sourceTree = "<group>"; };
@@ -124,7 +293,6 @@
B5D372831A39CD6900F583D9 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = "<group>"; };
B5D372851A39CDDB00F583D9 /* TestEntity1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestEntity1.swift; sourceTree = "<group>"; };
B5D39A0119FD00C9000E91BB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
B5D39A0319FD00DE000E91BB /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
B5D5E0CE1A4D6AAB006468AF /* TestEntity2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestEntity2.swift; sourceTree = "<group>"; };
B5D806C51A34715700A44484 /* GCDKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = GCDKit.xcodeproj; sourceTree = "<group>"; };
B5D9C8F61B160ED200E64F0E /* CoreStore.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = CoreStore.podspec; sourceTree = SOURCE_ROOT; };
@@ -140,7 +308,7 @@
B5E84EEA1AFF846E0064E85B /* AsynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsynchronousDataTransaction.swift; sourceTree = "<group>"; };
B5E84EEB1AFF846E0064E85B /* BaseDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseDataTransaction.swift; sourceTree = "<group>"; };
B5E84EEC1AFF846E0064E85B /* DataStack+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DataStack+Transaction.swift"; sourceTree = "<group>"; };
B5E84EED1AFF846E0064E85B /* DetachedDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetachedDataTransaction.swift; sourceTree = "<group>"; };
B5E84EED1AFF846E0064E85B /* UnsafeDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnsafeDataTransaction.swift; sourceTree = "<group>"; };
B5E84EEE1AFF846E0064E85B /* CoreStore+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Transaction.swift"; sourceTree = "<group>"; };
B5E84EF21AFF846E0064E85B /* SaveResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SaveResult.swift; sourceTree = "<group>"; };
B5E84EF31AFF846E0064E85B /* SynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousDataTransaction.swift; sourceTree = "<group>"; };
@@ -169,6 +337,8 @@
B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Transaction.swift"; sourceTree = "<group>"; };
B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Querying.swift"; sourceTree = "<group>"; };
B5E84F401AFF8CCD0064E85B /* ClauseTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClauseTypes.swift; sourceTree = "<group>"; };
B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableObject.swift; sourceTree = "<group>"; };
B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableUniqueObject.swift; sourceTree = "<group>"; };
B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSProgress+Convenience.swift"; sourceTree = "<group>"; };
B5FAD6AB1B51285300714891 /* MigrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationManager.swift; sourceTree = "<group>"; };
B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Migration.swift"; sourceTree = "<group>"; };
@@ -180,7 +350,6 @@
buildActionMask = 2147483647;
files = (
B5D8080E1A3471A500A44484 /* GCDKit.framework in Frameworks */,
B5D39A0419FD00DE000E91BB /* UIKit.framework in Frameworks */,
B5D39A0219FD00C9000E91BB /* Foundation.framework in Frameworks */,
2F03A54D19C5C872005002A5 /* CoreData.framework in Frameworks */,
);
@@ -193,6 +362,34 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
B52DD1701BE1F8CC00949AFE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B52DD1921BE1F8F000949AFE /* CoreData.framework in Frameworks */,
B52DD1911BE1F8EB00949AFE /* Foundation.framework in Frameworks */,
B52DD1901BE1F8E600949AFE /* GCDKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B52DD17A1BE1F8CC00949AFE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B52DD17E1BE1F8CD00949AFE /* CoreStore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B563216B1BD65082006C9394 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B563217D1BD650FA006C9394 /* GCDKit.framework in Frameworks */,
B563217C1BD650E3006C9394 /* Foundation.framework in Frameworks */,
B563217A1BD650DE006C9394 /* CoreData.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -212,6 +409,9 @@
children = (
2F03A53019C5C6DA005002A5 /* CoreStore.framework */,
2F03A53B19C5C6DA005002A5 /* CoreStoreTests.xctest */,
B563216F1BD65082006C9394 /* CoreStore.framework */,
B52DD1741BE1F8CC00949AFE /* CoreStore.framework */,
B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -270,9 +470,12 @@
2F291E3119C6D4D3007AF63F /* Frameworks */ = {
isa = PBXGroup;
children = (
B5548CD71BD65AE50077652A /* CoreData.framework */,
B56321791BD650DE006C9394 /* CoreData.framework */,
2F03A54C19C5C872005002A5 /* CoreData.framework */,
B5548CD51BD65AE00077652A /* Foundation.framework */,
B563217B1BD650E3006C9394 /* Foundation.framework */,
B5D39A0119FD00C9000E91BB /* Foundation.framework */,
B5D39A0319FD00DE000E91BB /* UIKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -309,7 +512,10 @@
isa = PBXGroup;
children = (
B5D808021A34715700A44484 /* GCDKit.framework */,
B5D808041A34715700A44484 /* GCDKitTests.xctest */,
B5D808041A34715700A44484 /* GCDKitTests iOS.xctest */,
B56321651BD64F99006C9394 /* GCDKit.framework */,
B56321671BD64F99006C9394 /* GCDKitTests OSX.xctest */,
B56321691BD64F99006C9394 /* GCDKit.framework */,
);
name = Products;
sourceTree = "<group>";
@@ -317,6 +523,8 @@
B5E834B61B7630BD001D3D50 /* Importing Data */ = {
isa = PBXGroup;
children = (
B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */,
B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */,
B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */,
);
path = "Importing Data";
@@ -349,7 +557,7 @@
B5E84EEB1AFF846E0064E85B /* BaseDataTransaction.swift */,
B5E84EEA1AFF846E0064E85B /* AsynchronousDataTransaction.swift */,
B5E84EF31AFF846E0064E85B /* SynchronousDataTransaction.swift */,
B5E84EED1AFF846E0064E85B /* DetachedDataTransaction.swift */,
B5E84EED1AFF846E0064E85B /* UnsafeDataTransaction.swift */,
B5E84EEC1AFF846E0064E85B /* DataStack+Transaction.swift */,
B5E84EEE1AFF846E0064E85B /* CoreStore+Transaction.swift */,
B5E84EF21AFF846E0064E85B /* SaveResult.swift */,
@@ -417,8 +625,10 @@
isa = PBXGroup;
children = (
B5E84F2A1AFF849C0064E85B /* AssociatedObjects.swift */,
B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */,
B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */,
B5E834BA1B7691F3001D3D50 /* Functions.swift */,
B5FAD6AB1B51285300714891 /* MigrationManager.swift */,
B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */,
B59D5C211B5BA34B00453479 /* NSFileManager+Setup.swift */,
B5E84F341AFF85470064E85B /* NSManagedObject+Transaction.swift */,
B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */,
@@ -427,7 +637,6 @@
B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */,
B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */,
B5E84F2D1AFF849C0064E85B /* WeakObject.swift */,
B5E834BA1B7691F3001D3D50 /* Functions.swift */,
);
path = Internal;
sourceTree = "<group>";
@@ -443,12 +652,28 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
B52DD1711BE1F8CC00949AFE /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
B52DD1931BE1F8FD00949AFE /* CoreStore.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B563216C1BD65082006C9394 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
B563217E1BD65110006C9394 /* CoreStore.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
2F03A52F19C5C6DA005002A5 /* CoreStore */ = {
2F03A52F19C5C6DA005002A5 /* CoreStore iOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2F03A54319C5C6DA005002A5 /* Build configuration list for PBXNativeTarget "CoreStore" */;
buildConfigurationList = 2F03A54319C5C6DA005002A5 /* Build configuration list for PBXNativeTarget "CoreStore iOS" */;
buildPhases = (
2F03A52B19C5C6DA005002A5 /* Sources */,
2F03A52C19C5C6DA005002A5 /* Frameworks */,
@@ -460,14 +685,14 @@
dependencies = (
B5D9C9091B20A87D00E64F0E /* PBXTargetDependency */,
);
name = CoreStore;
name = "CoreStore iOS";
productName = CoreStore;
productReference = 2F03A53019C5C6DA005002A5 /* CoreStore.framework */;
productType = "com.apple.product-type.framework";
};
2F03A53A19C5C6DA005002A5 /* CoreStoreTests */ = {
2F03A53A19C5C6DA005002A5 /* CoreStoreTests iOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2F03A54619C5C6DA005002A5 /* Build configuration list for PBXNativeTarget "CoreStoreTests" */;
buildConfigurationList = 2F03A54619C5C6DA005002A5 /* Build configuration list for PBXNativeTarget "CoreStoreTests iOS" */;
buildPhases = (
2F03A53719C5C6DA005002A5 /* Sources */,
2F03A53819C5C6DA005002A5 /* Frameworks */,
@@ -478,18 +703,74 @@
dependencies = (
B5D372881A39CF4D00F583D9 /* PBXTargetDependency */,
);
name = CoreStoreTests;
name = "CoreStoreTests iOS";
productName = CoreStoreTests;
productReference = 2F03A53B19C5C6DA005002A5 /* CoreStoreTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
B52DD1731BE1F8CC00949AFE /* CoreStore OSX */ = {
isa = PBXNativeTarget;
buildConfigurationList = B52DD18C1BE1F8CD00949AFE /* Build configuration list for PBXNativeTarget "CoreStore OSX" */;
buildPhases = (
B52DD16F1BE1F8CC00949AFE /* Sources */,
B52DD1701BE1F8CC00949AFE /* Frameworks */,
B52DD1711BE1F8CC00949AFE /* Headers */,
B52DD1721BE1F8CC00949AFE /* Resources */,
);
buildRules = (
);
dependencies = (
B52DD18F1BE1F8DC00949AFE /* PBXTargetDependency */,
);
name = "CoreStore OSX";
productName = "CoreStore OSX";
productReference = B52DD1741BE1F8CC00949AFE /* CoreStore.framework */;
productType = "com.apple.product-type.framework";
};
B52DD17C1BE1F8CC00949AFE /* CoreStoreTests OSX */ = {
isa = PBXNativeTarget;
buildConfigurationList = B52DD18D1BE1F8CD00949AFE /* Build configuration list for PBXNativeTarget "CoreStoreTests OSX" */;
buildPhases = (
B52DD1791BE1F8CC00949AFE /* Sources */,
B52DD17A1BE1F8CC00949AFE /* Frameworks */,
B52DD17B1BE1F8CC00949AFE /* Resources */,
);
buildRules = (
);
dependencies = (
B52DD1801BE1F8CD00949AFE /* PBXTargetDependency */,
);
name = "CoreStoreTests OSX";
productName = "CoreStore OSXTests";
productReference = B52DD17D1BE1F8CC00949AFE /* CoreStoreTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
B563216E1BD65082006C9394 /* CoreStore watchOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = B56321741BD65082006C9394 /* Build configuration list for PBXNativeTarget "CoreStore watchOS" */;
buildPhases = (
B563216A1BD65082006C9394 /* Sources */,
B563216B1BD65082006C9394 /* Frameworks */,
B563216C1BD65082006C9394 /* Headers */,
B563216D1BD65082006C9394 /* Resources */,
);
buildRules = (
);
dependencies = (
B56321781BD650A3006C9394 /* PBXTargetDependency */,
);
name = "CoreStore watchOS";
productName = "CoreStore watchOS";
productReference = B563216F1BD65082006C9394 /* CoreStore.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
2F03A52719C5C6DA005002A5 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastSwiftUpdateCheck = 0710;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = {
@@ -499,6 +780,15 @@
2F03A53A19C5C6DA005002A5 = {
CreatedOnToolsVersion = 6.0;
};
B52DD1731BE1F8CC00949AFE = {
CreatedOnToolsVersion = 7.1;
};
B52DD17C1BE1F8CC00949AFE = {
CreatedOnToolsVersion = 7.1;
};
B563216E1BD65082006C9394 = {
CreatedOnToolsVersion = 7.0.1;
};
};
};
buildConfigurationList = 2F03A52A19C5C6DA005002A5 /* Build configuration list for PBXProject "CoreStore" */;
@@ -520,13 +810,37 @@
);
projectRoot = "";
targets = (
2F03A52F19C5C6DA005002A5 /* CoreStore */,
2F03A53A19C5C6DA005002A5 /* CoreStoreTests */,
2F03A52F19C5C6DA005002A5 /* CoreStore iOS */,
2F03A53A19C5C6DA005002A5 /* CoreStoreTests iOS */,
B563216E1BD65082006C9394 /* CoreStore watchOS */,
B52DD1731BE1F8CC00949AFE /* CoreStore OSX */,
B52DD17C1BE1F8CC00949AFE /* CoreStoreTests OSX */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
B56321651BD64F99006C9394 /* GCDKit.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = GCDKit.framework;
remoteRef = B56321641BD64F99006C9394 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B56321671BD64F99006C9394 /* GCDKitTests OSX.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = "GCDKitTests OSX.xctest";
remoteRef = B56321661BD64F99006C9394 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B56321691BD64F99006C9394 /* GCDKit.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = GCDKit.framework;
remoteRef = B56321681BD64F99006C9394 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B5D808021A34715700A44484 /* GCDKit.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
@@ -534,10 +848,10 @@
remoteRef = B5D808011A34715700A44484 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B5D808041A34715700A44484 /* GCDKitTests.xctest */ = {
B5D808041A34715700A44484 /* GCDKitTests iOS.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = GCDKitTests.xctest;
path = "GCDKitTests iOS.xctest";
remoteRef = B5D808031A34715700A44484 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
@@ -558,6 +872,27 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
B52DD1721BE1F8CC00949AFE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
B52DD17B1BE1F8CC00949AFE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
B563216D1BD65082006C9394 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -566,9 +901,11 @@
buildActionMask = 2147483647;
files = (
B5E84F221AFF84860064E85B /* ObjectMonitor.swift in Sources */,
B5F1DA901B9AA991007C5CBB /* ImportableUniqueObject.swift in Sources */,
B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */,
B5D1E22C19FA9FBC003B2874 /* NSError+CoreStore.swift in Sources */,
B5E84F131AFF847B0064E85B /* Where.swift in Sources */,
B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */,
B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */,
B5E84F141AFF847B0064E85B /* DataStack+Querying.swift in Sources */,
B56007141B3F6C2800A9A8F9 /* SectionBy.swift in Sources */,
@@ -584,6 +921,7 @@
B5E84EE11AFF84500064E85B /* PersistentStoreResult.swift in Sources */,
B5E84F251AFF84860064E85B /* ObjectObserver.swift in Sources */,
B5E84F2F1AFF849C0064E85B /* NotificationObserver.swift in Sources */,
B5F1DA8D1B9AA97D007C5CBB /* ImportableObject.swift in Sources */,
B5E84F381AFF85470064E85B /* NSManagedObject+Transaction.swift in Sources */,
B56965241B356B820075EE4A /* MigrationResult.swift in Sources */,
2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */,
@@ -594,7 +932,7 @@
B5E84EDF1AFF84500064E85B /* DataStack.swift in Sources */,
B5E834BB1B7691F3001D3D50 /* Functions.swift in Sources */,
B5E84F231AFF84860064E85B /* ListMonitor.swift in Sources */,
B5E84EF71AFF846E0064E85B /* DetachedDataTransaction.swift in Sources */,
B5E84EF71AFF846E0064E85B /* UnsafeDataTransaction.swift in Sources */,
B56964D41B22FFAD0075EE4A /* DataStack+Migration.swift in Sources */,
B5E84EF51AFF846E0064E85B /* BaseDataTransaction.swift in Sources */,
B5E84EFB1AFF846E0064E85B /* SaveResult.swift in Sources */,
@@ -632,12 +970,156 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
B52DD16F1BE1F8CC00949AFE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B52DD1BE1BE1F94300949AFE /* NSProgress+Convenience.swift in Sources */,
B52DD1951BE1F92500949AFE /* NSError+CoreStore.swift in Sources */,
B52DD1C21BE1F94600949AFE /* MigrationManager.swift in Sources */,
B52DD1AB1BE1F93900949AFE /* From.swift in Sources */,
B52DD1BF1BE1F94600949AFE /* AssociatedObjects.swift in Sources */,
B52DD1A11BE1F92C00949AFE /* DataStack+Transaction.swift in Sources */,
B52DD19E1BE1F92C00949AFE /* AsynchronousDataTransaction.swift in Sources */,
B52DD1981BE1F92500949AFE /* CoreStore+Setup.swift in Sources */,
B52DD1941BE1F92500949AFE /* CoreStore.swift in Sources */,
B52DD1A61BE1F92F00949AFE /* BaseDataTransaction+Importing.swift in Sources */,
B52DD1A91BE1F93200949AFE /* CoreStore+Querying.swift in Sources */,
B52DD1961BE1F92500949AFE /* DataStack.swift in Sources */,
B52DD1BD1BE1F94300949AFE /* NSManagedObject+Convenience.swift in Sources */,
B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */,
B52DD1C41BE1F94600949AFE /* NSFileManager+Setup.swift in Sources */,
B52DD1AC1BE1F93900949AFE /* Select.swift in Sources */,
B52DD1971BE1F92500949AFE /* PersistentStoreResult.swift in Sources */,
B52DD1C71BE1F94600949AFE /* NSManagedObjectContext+Querying.swift in Sources */,
B52DD1C81BE1F94600949AFE /* NSManagedObjectContext+Setup.swift in Sources */,
B52DD1C31BE1F94600949AFE /* NotificationObserver.swift in Sources */,
B52DD1A81BE1F93200949AFE /* DataStack+Querying.swift in Sources */,
B52DD1BC1BE1F94000949AFE /* MigrationResult.swift in Sources */,
B52DD19D1BE1F92C00949AFE /* BaseDataTransaction.swift in Sources */,
B52DD1B81BE1F94000949AFE /* DataStack+Migration.swift in Sources */,
B52DD1A51BE1F92F00949AFE /* ImportableUniqueObject.swift in Sources */,
B52DD19C1BE1F92C00949AFE /* Into.swift in Sources */,
B52DD1AF1BE1F93900949AFE /* GroupBy.swift in Sources */,
B52DD1B01BE1F93900949AFE /* Tweak.swift in Sources */,
B52DD1CA1BE1F94600949AFE /* NSManagedObjectModel+Setup.swift in Sources */,
B52DD1A41BE1F92F00949AFE /* ImportableObject.swift in Sources */,
B52DD1AE1BE1F93900949AFE /* OrderBy.swift in Sources */,
B52DD1BA1BE1F94000949AFE /* MigrationChain.swift in Sources */,
B52DD1C51BE1F94600949AFE /* NSManagedObject+Transaction.swift in Sources */,
B52DD1A31BE1F92C00949AFE /* SaveResult.swift in Sources */,
B52DD19F1BE1F92C00949AFE /* SynchronousDataTransaction.swift in Sources */,
B52DD1CB1BE1F94600949AFE /* WeakObject.swift in Sources */,
B52DD1C11BE1F94600949AFE /* Functions.swift in Sources */,
B52DD19A1BE1F92800949AFE /* CoreStore+Logging.swift in Sources */,
B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */,
B52DD1C61BE1F94600949AFE /* NSManagedObjectContext+CoreStore.swift in Sources */,
B52DD1A21BE1F92C00949AFE /* CoreStore+Transaction.swift in Sources */,
B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */,
B52DD1BB1BE1F94000949AFE /* MigrationType.swift in Sources */,
B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */,
B52DD19B1BE1F92800949AFE /* CoreStoreLogger.swift in Sources */,
B52DD1991BE1F92800949AFE /* DefaultLogger.swift in Sources */,
B52DD1B91BE1F94000949AFE /* CoreStore+Migration.swift in Sources */,
B52DD1AA1BE1F93500949AFE /* ClauseTypes.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B52DD1791BE1F8CC00949AFE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B52DD1CD1BE1F94D00949AFE /* TestEntity1.swift in Sources */,
B52DD1CE1BE1F94D00949AFE /* TestEntity2.swift in Sources */,
B52DD1CC1BE1F94D00949AFE /* CoreStoreTests.swift in Sources */,
B5598BCC1BE2093D0092EFCE /* Model.xcdatamodeld in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B563216A1BD65082006C9394 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B56321A91BD65219006C9394 /* NSProgress+Convenience.swift in Sources */,
B56321801BD65216006C9394 /* NSError+CoreStore.swift in Sources */,
B56321AD1BD6521C006C9394 /* MigrationManager.swift in Sources */,
B563219D1BD65216006C9394 /* DataStack+Observing.swift in Sources */,
B56321961BD65216006C9394 /* From.swift in Sources */,
B56321AA1BD6521C006C9394 /* AssociatedObjects.swift in Sources */,
B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */,
B563219E1BD65216006C9394 /* CoreStore+Observing.swift in Sources */,
B56321891BD65216006C9394 /* AsynchronousDataTransaction.swift in Sources */,
B56321831BD65216006C9394 /* CoreStore+Setup.swift in Sources */,
B563217F1BD65216006C9394 /* CoreStore.swift in Sources */,
B56321911BD65216006C9394 /* BaseDataTransaction+Importing.swift in Sources */,
B56321941BD65216006C9394 /* CoreStore+Querying.swift in Sources */,
B56321811BD65216006C9394 /* DataStack.swift in Sources */,
B56321A81BD65219006C9394 /* NSManagedObject+Convenience.swift in Sources */,
B56321981BD65216006C9394 /* Where.swift in Sources */,
B56321AF1BD6521C006C9394 /* NSFileManager+Setup.swift in Sources */,
B56321971BD65216006C9394 /* Select.swift in Sources */,
B56321AB1BD6521C006C9394 /* FetchedResultsControllerDelegate.swift in Sources */,
B56321821BD65216006C9394 /* PersistentStoreResult.swift in Sources */,
B563219C1BD65216006C9394 /* SectionBy.swift in Sources */,
B56321B21BD6521C006C9394 /* NSManagedObjectContext+Querying.swift in Sources */,
B56321B31BD6521C006C9394 /* NSManagedObjectContext+Setup.swift in Sources */,
B56321AE1BD6521C006C9394 /* NotificationObserver.swift in Sources */,
B56321931BD65216006C9394 /* DataStack+Querying.swift in Sources */,
B56321A71BD65216006C9394 /* MigrationResult.swift in Sources */,
B56321A11BD65216006C9394 /* ListMonitor.swift in Sources */,
B56321881BD65216006C9394 /* BaseDataTransaction.swift in Sources */,
B56321A31BD65216006C9394 /* DataStack+Migration.swift in Sources */,
B56321901BD65216006C9394 /* ImportableUniqueObject.swift in Sources */,
B56321871BD65216006C9394 /* Into.swift in Sources */,
B563219A1BD65216006C9394 /* GroupBy.swift in Sources */,
B563219B1BD65216006C9394 /* Tweak.swift in Sources */,
B56321B51BD6521C006C9394 /* NSManagedObjectModel+Setup.swift in Sources */,
B563218F1BD65216006C9394 /* ImportableObject.swift in Sources */,
B56321991BD65216006C9394 /* OrderBy.swift in Sources */,
B56321A51BD65216006C9394 /* MigrationChain.swift in Sources */,
B56321B01BD6521C006C9394 /* NSManagedObject+Transaction.swift in Sources */,
B563218E1BD65216006C9394 /* SaveResult.swift in Sources */,
B56321A21BD65216006C9394 /* ListObserver.swift in Sources */,
B563218A1BD65216006C9394 /* SynchronousDataTransaction.swift in Sources */,
B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */,
B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */,
B56321AC1BD6521C006C9394 /* Functions.swift in Sources */,
B56321851BD65216006C9394 /* CoreStore+Logging.swift in Sources */,
B56321921BD65216006C9394 /* BaseDataTransaction+Querying.swift in Sources */,
B56321B11BD6521C006C9394 /* NSManagedObjectContext+CoreStore.swift in Sources */,
B563218D1BD65216006C9394 /* CoreStore+Transaction.swift in Sources */,
B563218B1BD65216006C9394 /* UnsafeDataTransaction.swift in Sources */,
B56321A61BD65216006C9394 /* MigrationType.swift in Sources */,
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */,
B56321861BD65216006C9394 /* CoreStoreLogger.swift in Sources */,
B56321841BD65216006C9394 /* DefaultLogger.swift in Sources */,
B56321A41BD65216006C9394 /* CoreStore+Migration.swift in Sources */,
B56321A01BD65216006C9394 /* ObjectObserver.swift in Sources */,
B56321951BD65216006C9394 /* ClauseTypes.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
B52DD1801BE1F8CD00949AFE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = B52DD1731BE1F8CC00949AFE /* CoreStore OSX */;
targetProxy = B52DD17F1BE1F8CD00949AFE /* PBXContainerItemProxy */;
};
B52DD18F1BE1F8DC00949AFE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "GCDKit OSX";
targetProxy = B52DD18E1BE1F8DC00949AFE /* PBXContainerItemProxy */;
};
B56321781BD650A3006C9394 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "GCDKit watchOS";
targetProxy = B56321771BD650A3006C9394 /* PBXContainerItemProxy */;
};
B5D372881A39CF4D00F583D9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2F03A52F19C5C6DA005002A5 /* CoreStore */;
target = 2F03A52F19C5C6DA005002A5 /* CoreStore iOS */;
targetProxy = B5D372871A39CF4D00F583D9 /* PBXContainerItemProxy */;
};
B5D9C9091B20A87D00E64F0E /* PBXTargetDependency */ = {
@@ -750,9 +1232,9 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_SWIFT_FLAGS = "-D DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_NAME = CoreStore;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
@@ -770,7 +1252,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_NAME = CoreStore;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
};
@@ -780,10 +1262,6 @@
isa = XCBuildConfiguration;
buildSettings = {
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
@@ -791,7 +1269,7 @@
INFOPLIST_FILE = CoreStoreTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_NAME = CoreStoreTests;
};
name = Debug;
};
@@ -799,14 +1277,137 @@
isa = XCBuildConfiguration;
buildSettings = {
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = CoreStoreTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.johnestropia.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_NAME = CoreStoreTests;
};
name = Release;
};
B52DD1851BE1F8CD00949AFE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = CoreStore/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
PRODUCT_NAME = CoreStore;
SDKROOT = macosx;
SKIP_INSTALL = YES;
};
name = Debug;
};
B52DD1861BE1F8CD00949AFE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = CoreStore/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
PRODUCT_NAME = CoreStore;
SDKROOT = macosx;
SKIP_INSTALL = YES;
};
name = Release;
};
B52DD1871BE1F8CD00949AFE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = CoreStore/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11;
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
PRODUCT_NAME = CoreStoreTests;
SDKROOT = macosx;
};
name = Debug;
};
B52DD1881BE1F8CD00949AFE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = CoreStore/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11;
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
PRODUCT_NAME = CoreStoreTests;
SDKROOT = macosx;
};
name = Release;
};
B56321751BD65082006C9394 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = CoreStore/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
PRODUCT_NAME = CoreStore;
SDKROOT = watchos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
name = Debug;
};
B56321761BD65082006C9394 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_NO_COMMON_BLOCKS = YES;
INFOPLIST_FILE = CoreStore/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.CoreStore;
PRODUCT_NAME = CoreStore;
SDKROOT = watchos;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
name = Release;
};
@@ -822,7 +1423,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
2F03A54319C5C6DA005002A5 /* Build configuration list for PBXNativeTarget "CoreStore" */ = {
2F03A54319C5C6DA005002A5 /* Build configuration list for PBXNativeTarget "CoreStore iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2F03A54419C5C6DA005002A5 /* Debug */,
@@ -831,7 +1432,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
2F03A54619C5C6DA005002A5 /* Build configuration list for PBXNativeTarget "CoreStoreTests" */ = {
2F03A54619C5C6DA005002A5 /* Build configuration list for PBXNativeTarget "CoreStoreTests iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2F03A54719C5C6DA005002A5 /* Debug */,
@@ -840,6 +1441,33 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B52DD18C1BE1F8CD00949AFE /* Build configuration list for PBXNativeTarget "CoreStore OSX" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B52DD1851BE1F8CD00949AFE /* Debug */,
B52DD1861BE1F8CD00949AFE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B52DD18D1BE1F8CD00949AFE /* Build configuration list for PBXNativeTarget "CoreStoreTests OSX" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B52DD1871BE1F8CD00949AFE /* Debug */,
B52DD1881BE1F8CD00949AFE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B56321741BD65082006C9394 /* Build configuration list for PBXNativeTarget "CoreStore watchOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B56321751BD65082006C9394 /* Debug */,
B56321761BD65082006C9394 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B52DD1731BE1F8CC00949AFE"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore OSX"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B52DD17C1BE1F8CC00949AFE"
BuildableName = "CoreStoreTests.xctest"
BlueprintName = "CoreStoreTests OSX"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B52DD1731BE1F8CC00949AFE"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore OSX"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B52DD1731BE1F8CC00949AFE"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore OSX"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B52DD1731BE1F8CC00949AFE"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore OSX"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -16,7 +16,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A52F19C5C6DA005002A5"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore"
BlueprintName = "CoreStore iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@@ -30,7 +30,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A53A19C5C6DA005002A5"
BuildableName = "CoreStoreTests.xctest"
BlueprintName = "CoreStoreTests"
BlueprintName = "CoreStoreTests iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@@ -48,7 +48,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A53A19C5C6DA005002A5"
BuildableName = "CoreStoreTests.xctest"
BlueprintName = "CoreStoreTests"
BlueprintName = "CoreStoreTests iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</TestableReference>
@@ -58,7 +58,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A52F19C5C6DA005002A5"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore"
BlueprintName = "CoreStore iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
@@ -80,7 +80,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A52F19C5C6DA005002A5"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore"
BlueprintName = "CoreStore iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
@@ -98,7 +98,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "2F03A52F19C5C6DA005002A5"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore"
BlueprintName = "CoreStore iOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B563216E1BD65082006C9394"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore watchOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B563216E1BD65082006C9394"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore watchOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B563216E1BD65082006C9394"
BuildableName = "CoreStore.framework"
BlueprintName = "CoreStore watchOS"
ReferencedContainer = "container:CoreStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -37,6 +37,7 @@ public extension NSManagedObject {
- parameter KVCKey: the KVC key
- returns: the primitive value for the KVC key
*/
@warn_unused_result
public func accessValueForKVCKey(KVCKey: KeyPath) -> AnyObject? {
self.willAccessValueForKey(KVCKey)

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
FOUNDATION_EXPORT double CoreStoreVersionNumber;

View File

@@ -39,6 +39,7 @@ public extension BaseDataTransaction {
- 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.
*/
@warn_unused_result
public func fetchExisting<T: NSManagedObject>(object: T) -> T? {
do {
@@ -57,6 +58,7 @@ public extension BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object
- returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
*/
@warn_unused_result
public func fetchExisting<T: NSManagedObject>(objectID: NSManagedObjectID) -> T? {
do {
@@ -75,19 +77,10 @@ public extension BaseDataTransaction {
- parameter objects: an array of `NSManagedObject`s created/fetched outside the transaction
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
public func fetchExisting<T: NSManagedObject>(objects: [T]) -> [T] {
@warn_unused_result
public func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == T>(objects: S) -> [T] {
var existingObjects = [T]()
for object in objects {
do {
let existingObject = try self.context.existingObjectWithID(object.objectID) as! T
existingObjects.append(existingObject)
}
catch _ { }
}
return existingObjects
return objects.flatMap { (try? self.context.existingObjectWithID($0.objectID)) as? T }
}
/**
@@ -96,19 +89,10 @@ public extension BaseDataTransaction {
- parameter objectIDs: the `NSManagedObjectID` array for the objects
- returns: the `NSManagedObject` array for objects that exists in the transaction
*/
public func fetchExisting<T: NSManagedObject>(objectIDs: [NSManagedObjectID]) -> [T] {
@warn_unused_result
public func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == NSManagedObjectID>(objectIDs: S) -> [T] {
var existingObjects = [T]()
for objectID in objectIDs {
do {
let existingObject = try self.context.existingObjectWithID(objectID) as! T
existingObjects.append(existingObject)
}
catch _ { }
}
return existingObjects
return objectIDs.flatMap { (try? self.context.existingObjectWithID($0)) as? T }
}
/**
@@ -118,6 +102,7 @@ public extension BaseDataTransaction {
- 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(
@@ -135,6 +120,7 @@ public extension BaseDataTransaction {
- 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(
@@ -152,6 +138,7 @@ public extension BaseDataTransaction {
- 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
*/
@warn_unused_result
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
CoreStore.assert(
@@ -169,6 +156,7 @@ public extension BaseDataTransaction {
- 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
*/
@warn_unused_result
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
CoreStore.assert(
@@ -186,6 +174,7 @@ public extension BaseDataTransaction {
- 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(
@@ -203,6 +192,7 @@ public extension BaseDataTransaction {
- 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(
@@ -220,6 +210,7 @@ public extension BaseDataTransaction {
- 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
*/
@warn_unused_result
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
CoreStore.assert(
@@ -237,6 +228,7 @@ public extension BaseDataTransaction {
- 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
*/
@warn_unused_result
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
CoreStore.assert(
@@ -254,6 +246,7 @@ public extension BaseDataTransaction {
- 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
*/
@warn_unused_result
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
CoreStore.assert(
@@ -271,6 +264,7 @@ public extension BaseDataTransaction {
- 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
*/
@warn_unused_result
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
CoreStore.assert(
@@ -325,6 +319,7 @@ public extension BaseDataTransaction {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
CoreStore.assert(
@@ -345,6 +340,7 @@ public extension BaseDataTransaction {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
CoreStore.assert(
@@ -365,6 +361,7 @@ public extension BaseDataTransaction {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
CoreStore.assert(
@@ -385,6 +382,7 @@ public extension BaseDataTransaction {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
CoreStore.assert(

View File

@@ -24,6 +24,7 @@
//
import Foundation
import CoreData
public func +(left: OrderBy, right: OrderBy) -> OrderBy {

View File

@@ -406,11 +406,11 @@ extension Int8: SelectValueResultType {
public static func fromResultObject(result: AnyObject) -> Int8? {
if let value = (result as? NSNumber)?.longLongValue {
guard let value = (result as? NSNumber)?.longLongValue else {
return numericCast(value) as Int8
return nil
}
return nil
return numericCast(value) as Int8
}
}
@@ -426,11 +426,11 @@ extension Int16: SelectValueResultType {
public static func fromResultObject(result: AnyObject) -> Int16? {
if let value = (result as? NSNumber)?.longLongValue {
guard let value = (result as? NSNumber)?.longLongValue else {
return numericCast(value) as Int16
return nil
}
return nil
return numericCast(value) as Int16
}
}
@@ -446,11 +446,11 @@ extension Int32: SelectValueResultType {
public static func fromResultObject(result: AnyObject) -> Int32? {
if let value = (result as? NSNumber)?.longLongValue {
guard let value = (result as? NSNumber)?.longLongValue else {
return numericCast(value) as Int32
return nil
}
return nil
return numericCast(value) as Int32
}
}
@@ -482,11 +482,11 @@ extension Int: SelectValueResultType {
public static func fromResultObject(result: AnyObject) -> Int? {
if let value = (result as? NSNumber)?.longLongValue {
guard let value = (result as? NSNumber)?.longLongValue else {
return numericCast(value) as Int
return nil
}
return nil
return numericCast(value) as Int
}
}

View File

@@ -24,6 +24,7 @@
//
import Foundation
import CoreData
public func &&(left: Where, right: Where) -> Where {
@@ -102,16 +103,38 @@ public struct Where: FetchClause, QueryClause, DeleteClause {
}
/**
Initializes a `Where` clause with a predicate using the specified string format and arguments
Initializes a `Where` clause that compares equality
- parameter format: the format string for the predicate
- parameter argumentArray: the arguments for `format`
- parameter keyPath: the keyPath to compare with
- parameter value: the arguments for the `==` operator
*/
public init(_ keyPath: KeyPath, isEqualTo value: NSObject?) {
self.init(value == nil
? NSPredicate(format: "\(keyPath) == nil")
: NSPredicate(format: "\(keyPath) == %@", value!))
: NSPredicate(format: "\(keyPath) == %@", argumentArray: [value!]))
}
/**
Initializes a `Where` clause that compares membership
- parameter keyPath: the keyPath to compare with
- parameter list: the array to check membership of
*/
public init(_ keyPath: KeyPath, isMemberOf list: NSArray) {
self.init(NSPredicate(format: "\(keyPath) IN %@", list))
}
/**
Initializes a `Where` clause that compares membership
- parameter keyPath: the keyPath to compare with
- parameter list: the sequence to check membership of
*/
public init<S: SequenceType where S.Generator.Element: NSObject>(_ keyPath: KeyPath, isMemberOf list: S) {
self.init(NSPredicate(format: "\(keyPath) IN %@", Array(list) as NSArray))
}
public let predicate: NSPredicate

View File

@@ -24,6 +24,8 @@
//
import Foundation
import CoreData
// MARK: - CoreStore
@@ -37,6 +39,7 @@ public extension CoreStore {
- parameter object: a reference to the object created/fetched outside the `DataStack`
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
*/
@warn_unused_result
public static func fetchExisting<T: NSManagedObject>(object: T) -> T? {
return self.defaultStack.fetchExisting(object)
@@ -48,6 +51,7 @@ public extension CoreStore {
- parameter objectID: the `NSManagedObjectID` for the object
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
*/
@warn_unused_result
public static func fetchExisting<T: NSManagedObject>(objectID: NSManagedObjectID) -> T? {
return self.defaultStack.fetchExisting(objectID)
@@ -59,7 +63,8 @@ public extension CoreStore {
- parameter objects: an array of `NSManagedObject`s created/fetched outside the `DataStack`
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
*/
public static func fetchExisting<T: NSManagedObject>(objects: [T]) -> [T] {
@warn_unused_result
public static func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == T>(objects: S) -> [T] {
return self.defaultStack.fetchExisting(objects)
}
@@ -70,7 +75,8 @@ public extension CoreStore {
- parameter objectIDs: the `NSManagedObjectID` array for the objects
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
*/
public static func fetchExisting<T: NSManagedObject>(objectIDs: [NSManagedObjectID]) -> [T] {
@warn_unused_result
public static func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == NSManagedObjectID>(objectIDs: S) -> [T] {
return self.defaultStack.fetchExisting(objectIDs)
}
@@ -82,6 +88,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> T? {
return self.defaultStack.fetchOne(from, fetchClauses)
@@ -94,6 +101,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> T? {
return self.defaultStack.fetchOne(from, fetchClauses)
@@ -106,6 +114,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
return self.defaultStack.fetchAll(from, fetchClauses)
@@ -118,6 +127,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
return self.defaultStack.fetchAll(from, fetchClauses)
@@ -130,6 +140,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> Int? {
return self.defaultStack.fetchCount(from, fetchClauses)
@@ -142,6 +153,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchCount<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> Int? {
return self.defaultStack.fetchCount(from, fetchClauses)
@@ -154,6 +166,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
return self.defaultStack.fetchObjectID(from, fetchClauses)
@@ -166,6 +179,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
return self.defaultStack.fetchObjectID(from, fetchClauses)
@@ -178,6 +192,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
@@ -190,6 +205,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
*/
@warn_unused_result
public static func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
return self.defaultStack.fetchObjectIDs(from, fetchClauses)
@@ -205,6 +221,7 @@ public extension CoreStore {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public static func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
return self.defaultStack.queryValue(from, selectClause, queryClauses)
@@ -220,6 +237,7 @@ public extension CoreStore {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public static func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
return self.defaultStack.queryValue(from, selectClause, queryClauses)
@@ -235,6 +253,7 @@ public extension CoreStore {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public static func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
@@ -250,6 +269,7 @@ public extension CoreStore {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public static func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
return self.defaultStack.queryAttributes(from, selectClause, queryClauses)

View File

@@ -40,6 +40,7 @@ public extension DataStack {
- parameter object: a reference to the object created/fetched outside the `DataStack`
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
*/
@warn_unused_result
public func fetchExisting<T: NSManagedObject>(object: T) -> T? {
do {
@@ -58,6 +59,7 @@ public extension DataStack {
- parameter objectID: the `NSManagedObjectID` for the object
- returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
*/
@warn_unused_result
public func fetchExisting<T: NSManagedObject>(objectID: NSManagedObjectID) -> T? {
do {
@@ -76,19 +78,10 @@ public extension DataStack {
- parameter objects: an array of `NSManagedObject`s created/fetched outside the `DataStack`
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
*/
public func fetchExisting<T: NSManagedObject>(objects: [T]) -> [T] {
@warn_unused_result
public func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == T>(objects: S) -> [T] {
var existingObjects = [T]()
for object in objects {
do {
let existingObject = try self.mainContext.existingObjectWithID(object.objectID) as! T
existingObjects.append(existingObject)
}
catch _ { }
}
return existingObjects
return objects.flatMap { (try? self.mainContext.existingObjectWithID($0.objectID)) as? T }
}
/**
@@ -97,19 +90,10 @@ public extension DataStack {
- parameter objectIDs: the `NSManagedObjectID` array for the objects
- returns: the `NSManagedObject` array for objects that exists in the `DataStack`
*/
public func fetchExisting<T: NSManagedObject>(objectIDs: [NSManagedObjectID]) -> [T] {
@warn_unused_result
public func fetchExisting<T: NSManagedObject, S: SequenceType where S.Generator.Element == NSManagedObjectID>(objectIDs: S) -> [T] {
var existingObjects = [T]()
for objectID in objectIDs {
do {
let existingObject = try self.mainContext.existingObjectWithID(objectID) as! T
existingObjects.append(existingObject)
}
catch _ { }
}
return existingObjects
return objectIDs.flatMap { (try? self.mainContext.existingObjectWithID($0)) as? T }
}
/**
@@ -119,6 +103,7 @@ public extension DataStack {
- 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(
@@ -136,6 +121,7 @@ public extension DataStack {
- 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(
@@ -153,6 +139,7 @@ public extension DataStack {
- 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
*/
@warn_unused_result
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [T]? {
CoreStore.assert(
@@ -170,6 +157,7 @@ public extension DataStack {
- 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
*/
@warn_unused_result
public func fetchAll<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [T]? {
CoreStore.assert(
@@ -187,6 +175,7 @@ public extension DataStack {
- 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(
@@ -204,6 +193,7 @@ public extension DataStack {
- 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(
@@ -221,6 +211,7 @@ public extension DataStack {
- 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
*/
@warn_unused_result
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
CoreStore.assert(
@@ -238,6 +229,7 @@ public extension DataStack {
- 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
*/
@warn_unused_result
public func fetchObjectID<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
CoreStore.assert(
@@ -255,6 +247,7 @@ public extension DataStack {
- 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
*/
@warn_unused_result
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
CoreStore.assert(
@@ -272,6 +265,7 @@ public extension DataStack {
- 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
*/
@warn_unused_result
public func fetchObjectIDs<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
CoreStore.assert(
@@ -292,6 +286,7 @@ public extension DataStack {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: QueryClause...) -> U? {
CoreStore.assert(
@@ -312,6 +307,7 @@ public extension DataStack {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public func queryValue<T: NSManagedObject, U: SelectValueResultType>(from: From<T>, _ selectClause: Select<U>, _ queryClauses: [QueryClause]) -> U? {
CoreStore.assert(
@@ -332,6 +328,7 @@ public extension DataStack {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
CoreStore.assert(
@@ -352,6 +349,7 @@ public extension DataStack {
- parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
- returns: the result of the the query. The type of the return value is specified by the generic type of the `Select<U>` parameter.
*/
@warn_unused_result
public func queryAttributes<T: NSManagedObject>(from: From<T>, _ selectClause: Select<NSDictionary>, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
CoreStore.assert(

View File

@@ -27,41 +27,20 @@ import Foundation
import CoreData
public protocol ImportableObject: class {
typealias ImportSource
static func shouldImportFromSource(source: ImportSource) -> Bool
func didInsertFromImportSource(source: ImportSource) throws
func updateFromImportSource(source: ImportSource) throws
}
public extension ImportableObject {
static func shouldImportFromSource(source: ImportSource) -> Bool {
return true
}
}
public protocol ImportableUniqueObject: ImportableObject {
typealias UniqueIDType: NSObject
static var uniqueIDKeyPath: String { get }
var uniqueIDValue: UniqueIDType { get set }
static func uniqueIDFromImportSource(source: ImportSource) throws -> UniqueIDType
}
// MARK: - BaseDataTransaction
public extension BaseDataTransaction {
func importObject<T where T: NSManagedObject, T: ImportableObject>(
// MARK: Public
/**
Creates an `ImportableObject` by importing from the specified import source.
- parameter into: an `Into` clause specifying the entity type
- parameter source: the object to import values from
- returns: the created `ImportableObject` instance, or `nil` if the import was ignored
*/
public func importObject<T where T: NSManagedObject, T: ImportableObject>(
into: Into<T>,
source: T.ImportSource) throws -> T? {
@@ -72,67 +51,60 @@ public extension BaseDataTransaction {
return try autoreleasepool {
if !T.shouldImportFromSource(source) {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
return nil
}
let object = self.create(into)
try object.didInsertFromImportSource(source)
try object.didInsertFromImportSource(source, inTransaction: self)
return object
}
}
func importObjects<T where T: NSManagedObject, T: ImportableObject>(
/**
Creates multiple `ImportableObject`s by importing from the specified array of import sources.
- parameter into: an `Into` clause specifying the entity type
- parameter sourceArray: the array of objects to import values from
- returns: the array of created `ImportableObject` instances
*/
public func importObjects<T, S: SequenceType where T: NSManagedObject, T: ImportableObject, S.Generator.Element == T.ImportSource>(
into: Into<T>,
sourceArray: [T.ImportSource]) throws {
sourceArray: S) throws -> [T] {
CoreStore.assert(
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
)
try autoreleasepool {
return try autoreleasepool {
for source in sourceArray {
return try sourceArray.flatMap { (source) -> T? in
try autoreleasepool {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
return nil
}
return try autoreleasepool {
let object = self.create(into)
try object.didInsertFromImportSource(source)
try object.didInsertFromImportSource(source, inTransaction: self)
return object
}
}
}
}
func importObjects<T where T: NSManagedObject, T: ImportableObject>(
into: Into<T>,
sourceArray: [T.ImportSource],
postProcess: (sorted: [T]) -> Void) throws {
CoreStore.assert(
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
)
try autoreleasepool {
var objects = [T]()
for source in sourceArray {
try autoreleasepool {
let object = self.create(into)
try object.didInsertFromImportSource(source)
objects.append(object)
}
}
postProcess(sorted: objects)
}
}
/**
Updates an existing `ImportableUniqueObject` or creates a new instance by importing from the specified import source.
func importUniqueObject<T where T: NSManagedObject, T: ImportableUniqueObject>(
- parameter into: an `Into` clause specifying the entity type
- parameter source: the object to import values from
- returns: the created/updated `ImportableUniqueObject` instance, or `nil` if the import was ignored
*/
public func importUniqueObject<T where T: NSManagedObject, T: ImportableUniqueObject>(
into: Into<T>,
source: T.ImportSource) throws -> T? {
@@ -143,130 +115,83 @@ public extension BaseDataTransaction {
return try autoreleasepool {
if !T.shouldImportFromSource(source) {
let uniqueIDKeyPath = T.uniqueIDKeyPath
guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else {
return nil
}
let uniqueIDKeyPath = T.uniqueIDKeyPath
let uniqueIDValue = try T.uniqueIDFromImportSource(source)
if let object = self.fetchOne(From(T), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
try object.updateFromImportSource(source)
try object.updateFromImportSource(source, inTransaction: self)
return object
}
else {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
return nil
}
let object = self.create(into)
object.uniqueIDValue = uniqueIDValue
try object.didInsertFromImportSource(source)
try object.didInsertFromImportSource(source, inTransaction: self)
return object
}
}
}
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
into: Into<T>,
sourceArray: [T.ImportSource],
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> Void)? = nil) throws {
CoreStore.assert(
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
)
try autoreleasepool {
var mapping = Dictionary<T.UniqueIDType, T.ImportSource>()
for source in sourceArray {
try autoreleasepool {
if !T.shouldImportFromSource(source) {
return
}
let uniqueIDValue = try T.uniqueIDFromImportSource(source)
mapping[uniqueIDValue] = source
}
}
if let preProcess = preProcess {
try autoreleasepool {
try preProcess(mapping: mapping)
}
}
for object in self.fetchAll(From(T), Where("%K IN %@", T.uniqueIDKeyPath, mapping.keys.array)) ?? [] {
try autoreleasepool {
let uniqueIDValue = object.uniqueIDValue
try object.updateFromImportSource(mapping.removeValueForKey(uniqueIDValue)!)
}
}
for (uniqueIDValue, source) in mapping {
try autoreleasepool {
let object = self.create(into)
object.uniqueIDValue = uniqueIDValue
try object.didInsertFromImportSource(source)
}
}
}
}
/**
Updates existing `ImportableUniqueObject`s or creates them by importing from the specified array of import sources.
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
- parameter into: an `Into` clause specifying the entity type
- parameter sourceArray: the array of objects to import values from
- parameter preProcess: a closure that lets the caller tweak the internal `UniqueIDType`-to-`ImportSource` mapping to be used for importing. Callers can remove from/add to/update `mapping` and return the updated array from the closure.
- returns: the array of created/updated `ImportableUniqueObject` instances
*/
public func importUniqueObjects<T, S: SequenceType where T: NSManagedObject, T: ImportableUniqueObject, S.Generator.Element == T.ImportSource>(
into: Into<T>,
sourceArray: [T.ImportSource],
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> Void)? = nil,
postProcess: (sorted: [T]) -> Void) throws {
sourceArray: S,
@noescape preProcess: (mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource] = { $0 }) throws -> [T] {
CoreStore.assert(
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
"Attempted to import an object of type \(typeName(into.entityClass)) outside the transaction's designated queue."
)
try autoreleasepool {
return try autoreleasepool {
var sortedIDs = Array<T.UniqueIDType>()
var mapping = Dictionary<T.UniqueIDType, T.ImportSource>()
for source in sourceArray {
let sortedIDs = try autoreleasepool {
try autoreleasepool {
return try sourceArray.flatMap { (source) -> T.UniqueIDType? in
if !T.shouldImportFromSource(source) {
guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else {
return
return nil
}
let uniqueIDValue = try T.uniqueIDFromImportSource(source)
mapping[uniqueIDValue] = source
sortedIDs.append(uniqueIDValue)
return uniqueIDValue
}
}
if let preProcess = preProcess {
try autoreleasepool {
try preProcess(mapping: mapping)
}
}
mapping = try autoreleasepool { try preProcess(mapping: mapping) }
var objects = Dictionary<T.UniqueIDType, T>()
for object in self.fetchAll(From(T), Where("%K IN %@", T.uniqueIDKeyPath, mapping.keys.array)) ?? [] {
for object in self.fetchAll(From(T), Where(T.uniqueIDKeyPath, isMemberOf: mapping.keys)) ?? [] {
try autoreleasepool {
let uniqueIDValue = object.uniqueIDValue
try object.updateFromImportSource(mapping.removeValueForKey(uniqueIDValue)!)
guard let source = mapping.removeValueForKey(uniqueIDValue)
where T.shouldUpdateFromImportSource(source, inTransaction: self) else {
return
}
try object.updateFromImportSource(source, inTransaction: self)
objects[uniqueIDValue] = object
}
}
@@ -275,15 +200,20 @@ public extension BaseDataTransaction {
try autoreleasepool {
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
return
}
let object = self.create(into)
object.uniqueIDValue = uniqueIDValue
try object.didInsertFromImportSource(source)
try object.didInsertFromImportSource(source, inTransaction: self)
objects[uniqueIDValue] = object
}
}
postProcess(sorted: sortedIDs.flatMap { objects[$0] })
return sortedIDs.flatMap { objects[$0] }
}
}
}

View File

@@ -0,0 +1,84 @@
//
// ImportableObject.swift
// CoreStore
//
// Copyright (c) 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: - ImportableObject
/**
`NSManagedObject` subclasses that conform to the `ImportableObject` protocol can be imported from a specified `ImportSource`. This allows transactions to create and insert instances this way:
class MyPersonEntity: NSManagedObject, ImportableObject {
typealias ImportSource = NSDictionary
// ...
}
CoreStore.beginAsynchronous { (transaction) -> Void in
let json: NSDictionary = // ...
let person = try! transaction.importObject(
Into(MyPersonEntity),
source: json
)
// ...
transaction.commit()
}
*/
public protocol ImportableObject: class {
/**
The data type for the import source. This is most commonly an `NSDictionary` or another external source such as an `NSUserDefaults`.
*/
typealias ImportSource
/**
Return `true` if an object should be created from `source`. Return `false` to ignore and skip `source`. The default implementation returns `true`.
- parameter source: the object to import from
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
- returns: `true` if an object should be created from `source`. Return `false` to ignore.
*/
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
/**
Implements the actual importing of data from `source`. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importObjects(:sourceArray:)` call to be cancelled.
- parameter source: the object to import from
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
*/
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
}
// MARK: - ImportableObject (Default Implementations)
public extension ImportableObject {
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
return true
}
}

View File

@@ -0,0 +1,136 @@
//
// ImportableUniqueObject.swift
// CoreStore
//
// Copyright (c) 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: - ImportableUniqueObject
/**
`NSManagedObject` subclasses that conform to the `ImportableUniqueObject` protocol can be imported from a specified `ImportSource`. This allows transactions to either update existing objects or create new instances this way:
class MyPersonEntity: NSManagedObject, ImportableUniqueObject {
typealias ImportSource = NSDictionary
typealias UniqueIDType = NSString
// ...
}
CoreStore.beginAsynchronous { (transaction) -> Void in
let json: NSDictionary = // ...
let person = try! transaction.importUniqueObject(
Into(MyPersonEntity),
source: json
)
// ...
transaction.commit()
}
*/
public protocol ImportableUniqueObject: ImportableObject {
/**
The data type for the import source. This is most commonly an `NSDictionary` or another external source such as an `NSUserDefaults`.
*/
typealias ImportSource
/**
The data type for the entity's unique ID attribute
*/
typealias UniqueIDType: NSObject
/**
The keyPath to the entity's unique ID attribute
*/
static var uniqueIDKeyPath: String { get }
/**
The object's unique ID value
*/
var uniqueIDValue: UniqueIDType { get set }
/**
Return `true` if an object should be created from `source`. Return `false` to ignore and skip `source`. The default implementation returns the value returned by the `shouldUpdateFromImportSource(:inTransaction:)` implementation.
- parameter source: the object to import from
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
- returns: `true` if an object should be created from `source`. Return `false` to ignore.
*/
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
/**
Return `true` if an object should be updated from `source`. Return `false` to ignore and skip `source`. The default implementation returns `true`.
- parameter source: the object to import from
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
- returns: `true` if an object should be updated from `source`. Return `false` to ignore.
*/
static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
/**
Return the unique ID as extracted from `source`. This method is called before `shouldInsertFromImportSource(...)` or `shouldUpdateFromImportSource(...)`. Return `nil` to skip importing from `source`. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled.
- parameter source: the object to import from
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
- returns: the unique ID as extracted from `source`, or `nil` to skip importing from `source`.
*/
static func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType?
/**
Implements the actual importing of data from `source`. This method is called just after the object is created and assigned its unique ID as returned from `uniqueIDFromImportSource(...)`. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled. The default implementation simply calls `updateFromImportSource(...)`.
- parameter source: the object to import from
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
*/
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
/**
Implements the actual importing of data from `source`. This method is called just after the existing object is fetched using its unique ID. Implementers should pull values from `source` and assign them to the receiver's attributes. Note that throwing from this method will cause subsequent imports that are part of the same `importUniqueObjects(:sourceArray:)` call to be cancelled.
- parameter source: the object to import from
- parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed.
*/
func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
}
// MARK: - ImportableUniqueObject (Default Implementations)
public extension ImportableUniqueObject {
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
return self.shouldUpdateFromImportSource(source, inTransaction: transaction)
}
static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
return true
}
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
try self.updateFromImportSource(source, inTransaction: transaction)
}
}

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.2.1</string>
<string>1.3.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View File

@@ -0,0 +1,219 @@
//
// FetchedResultsControllerDelegate.swift
// CoreStore
//
// Copyright (c) 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: - FetchedResultsControllerHandler
@available(OSX, unavailable)
internal protocol FetchedResultsControllerHandler: class {
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
func controllerWillChangeContent(controller: NSFetchedResultsController)
func controllerDidChangeContent(controller: NSFetchedResultsController)
func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String?
}
// MARK: - FetchedResultsControllerDelegate
@available(OSX, unavailable)
internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate {
// MARK: Internal
internal var enabled = true
internal weak var handler: FetchedResultsControllerHandler?
internal weak var fetchedResultsController: NSFetchedResultsController? {
didSet {
oldValue?.delegate = nil
self.fetchedResultsController?.delegate = self
}
}
deinit {
self.fetchedResultsController?.delegate = nil
}
// MARK: NSFetchedResultsControllerDelegate
@objc dynamic func controllerWillChangeContent(controller: NSFetchedResultsController) {
guard self.enabled else {
return
}
self.deletedSections = []
self.insertedSections = []
self.handler?.controllerWillChangeContent(controller)
}
@objc dynamic func controllerDidChangeContent(controller: NSFetchedResultsController) {
guard self.enabled else {
return
}
self.handler?.controllerDidChangeContent(controller)
}
@objc dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
guard self.enabled else {
return
}
guard let actualType = NSFetchedResultsChangeType(rawValue: type.rawValue) else {
// This fix is for a bug where iOS passes 0 for NSFetchedResultsChangeType, but this is not a valid enum case.
// Swift will then always execute the first case of the switch causing strange behaviour.
// https://forums.developer.apple.com/thread/12184#31850
return
}
// This whole dance is a workaround for a nasty bug introduced in XCode 7 targeted at iOS 8 devices
// http://stackoverflow.com/questions/31383760/ios-9-attempt-to-delete-and-reload-the-same-index-path/31384014#31384014
// https://forums.developer.apple.com/message/9998#9998
// https://forums.developer.apple.com/message/31849#31849
switch actualType {
case .Update:
guard let section = indexPath?.indexAtPosition(0) else {
return
}
if self.deletedSections.contains(section)
|| self.insertedSections.contains(section) {
return
}
case .Move:
guard let indexPath = indexPath, let newIndexPath = newIndexPath else {
return
}
guard indexPath == newIndexPath else {
break
}
if self.insertedSections.contains(indexPath.indexAtPosition(0)) {
// Observers that handle the .Move change are advised to delete then reinsert the object instead of just moving. This is especially true when indexPath and newIndexPath are equal. For example, calling tableView.moveRowAtIndexPath(_:toIndexPath) when both indexPaths are the same will crash the tableView.
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: indexPath,
forChangeType: .Move,
newIndexPath: newIndexPath
)
return
}
if self.deletedSections.contains(indexPath.indexAtPosition(0)) {
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: nil,
forChangeType: .Insert,
newIndexPath: indexPath
)
return
}
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: indexPath,
forChangeType: .Update,
newIndexPath: nil
)
return
default:
break
}
self.handler?.controller(
controller,
didChangeObject: anObject,
atIndexPath: indexPath,
forChangeType: actualType,
newIndexPath: newIndexPath
)
}
@objc dynamic func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
guard self.enabled else {
return
}
switch type {
case .Delete: self.deletedSections.insert(sectionIndex)
case .Insert: self.insertedSections.insert(sectionIndex)
default: break
}
self.handler?.controller(
controller,
didChangeSection: sectionInfo,
atIndex: sectionIndex,
forChangeType: type
)
}
@objc dynamic func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String) -> String? {
return self.handler?.controller(
controller,
sectionIndexTitleForSectionName: sectionName
)
}
// MARK: Private
private var deletedSections = Set<Int>()
private var insertedSections = Set<Int>()
}

View File

@@ -25,9 +25,9 @@
import Foundation
internal func autoreleasepool<T>(@noescape closure: () -> T?) -> T? {
internal func autoreleasepool<T>(@noescape closure: () -> T) -> T {
var closureValue: T?
var closureValue: T!
ObjectiveC.autoreleasepool {
closureValue = closure()
@@ -36,9 +36,9 @@ internal func autoreleasepool<T>(@noescape closure: () -> T?) -> T? {
return closureValue
}
internal func autoreleasepool<T>(@noescape closure: () throws -> T?) throws -> T? {
internal func autoreleasepool<T>(@noescape closure: () throws -> T) throws -> T {
var closureValue: T?
var closureValue: T!
var closureError: ErrorType?
ObjectiveC.autoreleasepool {

View File

@@ -37,11 +37,12 @@ internal final class MigrationManager: NSMigrationManager, NSProgressReporting {
super.didChangeValueForKey(key)
if key == "migrationProgress" {
guard key == "migrationProgress" else {
let progress = self.progress
progress.completedUnitCount = Int64(Float(progress.totalUnitCount) * self.migrationProgress)
return
}
let progress = self.progress
progress.completedUnitCount = Int64(Float(progress.totalUnitCount) * self.migrationProgress)
}

View File

@@ -17,22 +17,10 @@ internal extension NSFileManager {
internal func removeSQLiteStoreAtURL(fileURL: NSURL) {
do {
try self.removeItemAtURL(fileURL)
}
catch _ { }
_ = try? self.removeItemAtURL(fileURL)
do {
try self.removeItemAtPath(fileURL.path!.stringByAppendingString("-shm"))
}
catch _ { }
do {
try self.removeItemAtPath(fileURL.path!.stringByAppendingString("-wal"))
}
catch _ { }
let filePath = fileURL.path!
_ = try? self.removeItemAtPath(filePath.stringByAppendingString("-shm"))
_ = try? self.removeItemAtPath(filePath.stringByAppendingString("-wal"))
}
}

View File

@@ -41,82 +41,8 @@ internal extension NSManagedObject {
)
}
internal dynamic class func inContext(context: NSManagedObjectContext, withObjectID objectID: NSManagedObjectID) -> Self? {
return self.typedObjectInContext(context, objectID: objectID)
}
internal func inContext(context: NSManagedObjectContext) -> Self? {
return self.typedObjectInContext(context)
}
internal func deleteFromContext() {
self.managedObjectContext?.deleteObject(self)
}
// MARK: Private
private class func typedObjectInContext<T: NSManagedObject>(context: NSManagedObjectContext, objectID: NSManagedObjectID) -> T? {
do {
let existingObject = try context.existingObjectWithID(objectID)
return (existingObject as! T)
}
catch {
CoreStore.handleError(
error as NSError,
"Failed to load existing \(typeName(self)) in context."
)
return nil
}
}
private func typedObjectInContext<T: NSManagedObject>(context: NSManagedObjectContext) -> T? {
let objectID = self.objectID
if objectID.temporaryID {
var objectIDError: NSError?
let didSucceed = withExtendedLifetime(self.managedObjectContext) { (context: NSManagedObjectContext?) -> Bool in
do {
try context?.obtainPermanentIDsForObjects([self])
return true
}
catch {
objectIDError = error as NSError
return false
}
}
if didSucceed != true {
CoreStore.handleError(
objectIDError ?? NSError(coreStoreErrorCode: .UnknownError),
"Failed to obtain permanent ID for object."
)
return nil
}
}
do {
let existingObject = try context.existingObjectWithID(objectID)
return (existingObject as! T)
}
catch {
CoreStore.handleError(
error as NSError,
"Failed to load existing \(typeName(self)) in context."
)
return nil
}
}
}

View File

@@ -61,14 +61,14 @@ internal extension NSManagedObjectContext {
internal func entityDescriptionForEntityClass(entity: AnyClass) -> NSEntityDescription? {
if let entityName = self.parentStack?.entityNameForEntityClass(entity) {
return NSEntityDescription.entityForName(
entityName,
inManagedObjectContext: self
)
guard let entityName = self.parentStack?.entityNameForEntityClass(entity) else {
return nil
}
return nil
return NSEntityDescription.entityForName(
entityName,
inManagedObjectContext: self
)
}
internal func setupForCoreStoreWithContextName(contextName: String) {
@@ -83,7 +83,7 @@ internal extension NSManagedObjectContext {
let context = note.object as! NSManagedObjectContext
let insertedObjects = context.insertedObjects
let numberOfInsertedObjects = insertedObjects.count
if numberOfInsertedObjects <= 0 {
guard numberOfInsertedObjects > 0 else {
return
}
@@ -91,7 +91,6 @@ internal extension NSManagedObjectContext {
do {
try context.obtainPermanentIDsForObjects(Array(insertedObjects))
return
}
catch {

View File

@@ -31,7 +31,43 @@ import CoreData
internal extension NSManagedObjectContext {
// MARK: Public
// MARK: Internal
internal func fetchExisting<T: NSManagedObject>(object: T) -> T? {
if object.objectID.temporaryID {
do {
try withExtendedLifetime(self) { (context: NSManagedObjectContext) -> Void in
try context.obtainPermanentIDsForObjects([object])
}
}
catch {
CoreStore.handleError(
error as NSError,
"Failed to obtain permanent ID for object."
)
return nil
}
}
do {
let existingObject = try self.existingObjectWithID(object.objectID)
return (existingObject as! T)
}
catch {
CoreStore.handleError(
error as NSError,
"Failed to load existing \(typeName(object)) in context."
)
return nil
}
}
internal func fetchOne<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> T? {

View File

@@ -46,7 +46,7 @@ internal extension NSManagedObjectContext {
}
set {
if self.parentContext != nil {
guard self.parentContext == nil else {
return
}
@@ -84,6 +84,11 @@ internal extension NSManagedObjectContext {
context?.performBlock { () -> Void in
let updatedObjects = (note.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObject>) ?? []
for object in updatedObjects {
context?.objectWithID(object.objectID).willAccessValueForKey(nil)
}
context?.mergeChangesFromContextDidSaveNotification(note)
}
}

View File

@@ -71,7 +71,7 @@ internal extension NSManagedObjectContext {
self.performBlockAndWait { [unowned self] () -> Void in
if !self.hasChanges {
guard self.hasChanges else {
return
}
@@ -111,18 +111,15 @@ internal extension NSManagedObjectContext {
return result
}
internal func saveAsynchronouslyWithCompletion(completion: ((result: SaveResult) -> Void)?) {
internal func saveAsynchronouslyWithCompletion(completion: ((result: SaveResult) -> Void) = { _ in }) {
self.performBlock { () -> Void in
if !self.hasChanges {
guard self.hasChanges else {
if let completion = completion {
GCDQueue.Main.async {
GCDQueue.Main.async {
completion(result: SaveResult(hasChanges: false))
}
completion(result: SaveResult(hasChanges: false))
}
return
}
@@ -138,12 +135,9 @@ internal extension NSManagedObjectContext {
saveError,
"Failed to save \(typeName(NSManagedObjectContext))."
)
if let completion = completion {
GCDQueue.Main.async {
GCDQueue.Main.async {
completion(result: SaveResult(saveError))
}
completion(result: SaveResult(saveError))
}
return
}
@@ -152,7 +146,7 @@ internal extension NSManagedObjectContext {
parentContext.saveAsynchronouslyWithCompletion(completion)
}
else if let completion = completion {
else {
GCDQueue.Main.async {

View File

@@ -150,11 +150,11 @@ internal extension NSManagedObjectModel {
return self.entityNameMapping[NSStringFromClass(entityClass)]!
}
@nonobjc internal func entityMapping() -> [String: NSManagedObject.Type] {
@nonobjc internal func entityTypesMapping() -> [String: NSManagedObject.Type] {
return self.entityNameMapping.reduce([:]) { (var mapping, pair) in
mapping[pair.0] = (NSClassFromString(pair.1)! as! NSManagedObject.Type)
mapping[pair.1] = (NSClassFromString(pair.0)! as! NSManagedObject.Type)
return mapping
}
}
@@ -192,14 +192,15 @@ internal extension NSManagedObjectModel {
@nonobjc internal subscript(metadata: [String: AnyObject]) -> NSManagedObjectModel? {
if let modelHashes = metadata[NSStoreModelVersionHashesKey] as? [String : NSData] {
guard let modelHashes = metadata[NSStoreModelVersionHashesKey] as? [String : NSData] else {
for modelVersion in self.modelVersions ?? [] {
return nil
}
for modelVersion in self.modelVersions ?? [] {
if let versionModel = self[modelVersion] where modelHashes == versionModel.entityVersionHashesByName {
if let versionModel = self[modelVersion] where modelHashes == versionModel.entityVersionHashesByName {
return versionModel
}
return versionModel
}
}
return nil

View File

@@ -120,6 +120,7 @@ public extension CoreStore {
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
:return: an array of `MigrationType`s indicating the chain of migrations required for the store; or `nil` if either inspection of the store failed, or no mapping model was found/inferred. `MigrationType` acts as a `Bool` and evaluates to `false` if no migration is required, and `true` if either a lightweight or custom migration is needed.
*/
@warn_unused_result
public static func requiredMigrationsForSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles() as [NSBundle]) throws -> [MigrationType] {
return try self.defaultStack.requiredMigrationsForSQLiteStore(
@@ -137,6 +138,7 @@ public extension CoreStore {
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
:return: a `MigrationType` indicating the type of migration required for the store; or `nil` if either inspection of the store failed, or no mapping model was found/inferred. `MigrationType` acts as a `Bool` and evaluates to `false` if no migration is required, and `true` if either a lightweight or custom migration is needed.
*/
@warn_unused_result
public static func requiredMigrationsForSQLiteStore(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles() as [NSBundle]) throws -> [MigrationType] {
return try self.defaultStack.requiredMigrationsForSQLiteStore(

View File

@@ -117,40 +117,37 @@ public extension DataStack {
let coordinator = self.coordinator;
if let store = coordinator.persistentStoreForURL(fileURL) {
if store.type == NSSQLiteStoreType
&& store.configurationName == (configuration ?? Into.defaultConfigurationName) {
guard store.type == NSSQLiteStoreType
&& store.configurationName == (configuration ?? Into.defaultConfigurationName) else {
GCDQueue.Main.async {
completion(PersistentStoreResult(store))
}
return nil
let error = NSError(coreStoreErrorCode: .DifferentPersistentStoreExistsAtURL)
CoreStore.handleError(
error,
"Failed to add SQLite \(typeName(NSPersistentStore)) at \"\(fileURL)\" because a different \(typeName(NSPersistentStore)) at that URL already exists."
)
throw error
}
let error = NSError(coreStoreErrorCode: .DifferentPersistentStoreExistsAtURL)
CoreStore.handleError(
error,
"Failed to add SQLite \(typeName(NSPersistentStore)) at \"\(fileURL)\" because a different \(typeName(NSPersistentStore)) at that URL already exists."
)
throw error
GCDQueue.Main.async {
completion(PersistentStoreResult(store))
}
return nil
}
let fileManager = NSFileManager.defaultManager()
do {
try fileManager.createDirectoryAtURL(
fileURL.URLByDeletingLastPathComponent!,
withIntermediateDirectories: true,
attributes: nil
)
}
catch _ { }
_ = try? fileManager.createDirectoryAtURL(
fileURL.URLByDeletingLastPathComponent!,
withIntermediateDirectories: true,
attributes: nil
)
do {
let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(
NSSQLiteStoreType,
URL: fileURL
URL: fileURL,
options: self.optionsForSQLiteStore()
)
return self.upgradeSQLiteStoreIfNeeded(
@@ -269,7 +266,8 @@ public extension DataStack {
metadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(
NSSQLiteStoreType,
URL: fileURL
URL: fileURL,
options: self.optionsForSQLiteStore()
)
}
catch {
@@ -298,6 +296,7 @@ public extension DataStack {
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
:return: an array of `MigrationType`s indicating the chain of migrations required for the store; or `nil` if either inspection of the store failed, or no mapping model was found/inferred. `MigrationType` acts as a `Bool` and evaluates to `false` if no migration is required, and `true` if either a lightweight or custom migration is needed.
*/
@warn_unused_result
public func requiredMigrationsForSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles() as [NSBundle]) throws -> [MigrationType] {
return try requiredMigrationsForSQLiteStore(
@@ -318,6 +317,7 @@ public extension DataStack {
- parameter mappingModelBundles: an optional array of bundles to search mapping model files from. If not set, defaults to the `NSBundle.allBundles()`.
:return: a `MigrationType` indicating the type of migration required for the store; or `nil` if either inspection of the store failed, or no mapping model was found/inferred. `MigrationType` acts as a `Bool` and evaluates to `false` if no migration is required, and `true` if either a lightweight or custom migration is needed.
*/
@warn_unused_result
public func requiredMigrationsForSQLiteStore(fileURL fileURL: NSURL = defaultSQLiteStoreURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles() as [NSBundle]) throws -> [MigrationType] {
let metadata: [String : AnyObject]
@@ -325,7 +325,8 @@ public extension DataStack {
metadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(
NSSQLiteStoreType,
URL: fileURL
URL: fileURL,
options: self.optionsForSQLiteStore()
)
}
catch {
@@ -436,7 +437,7 @@ public extension DataStack {
let migrationOperation = NSBlockOperation()
migrationOperation.qualityOfService = .Utility
operations.map { migrationOperation.addDependency($0) }
operations.forEach { migrationOperation.addDependency($0) }
migrationOperation.addExecutionBlock { () -> Void in
GCDQueue.Main.async {

View File

@@ -166,12 +166,10 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
var valid = true
for version in elements {
if let lastVersion = lastVersion {
if let _ = versionTree.updateValue(version, forKey: lastVersion) {
if let lastVersion = lastVersion,
let _ = versionTree.updateValue(version, forKey: lastVersion) {
valid = false
}
}
lastVersion = version
}
@@ -203,11 +201,11 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
internal func nextVersionFrom(version: String) -> String? {
if let nextVersion = self.versionTree[version] where nextVersion != version {
guard let nextVersion = self.versionTree[version] where nextVersion != version else {
return nextVersion
return nil
}
return nil
return nextVersion
}
@@ -237,9 +235,9 @@ extension MigrationChain: CustomDebugStringConvertible {
steps.append(nextVersion)
version = nextVersion
}
paths.append("".join(steps))
paths.append(steps.joinWithSeparator(""))
}
return "[" + "], [".join(paths) + "]"
return "[" + paths.joinWithSeparator("], [") + "]"
}
}

View File

@@ -24,6 +24,7 @@
//
import Foundation
import CoreData
/**
The `NSError` error domain for `CoreStore`.

View File

@@ -29,6 +29,7 @@ import CoreData
// MARK: - CoreStore
@available(OSX, unavailable)
public extension CoreStore {
// MARK: Public
@@ -39,6 +40,7 @@ public extension CoreStore {
- parameter object: the `NSManagedObject` to observe changes from
- returns: a `ObjectMonitor` that monitors changes to `object`
*/
@warn_unused_result
public static func monitorObject<T: NSManagedObject>(object: T) -> ObjectMonitor<T> {
return self.defaultStack.monitorObject(object)
@@ -50,7 +52,8 @@ public extension CoreStore {
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
*/
@warn_unused_result
public static func monitorList<T: NSManagedObject>(from: From<T>, _ queryClauses: FetchClause...) -> ListMonitor<T> {
return self.defaultStack.monitorList(from, queryClauses)
@@ -63,6 +66,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
@warn_unused_result
public static func monitorList<T: NSManagedObject>(from: From<T>, _ queryClauses: [FetchClause]) -> ListMonitor<T> {
return self.defaultStack.monitorList(from, queryClauses)
@@ -76,6 +80,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
@warn_unused_result
public static func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
@@ -89,6 +94,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
@warn_unused_result
public static func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)

View File

@@ -30,6 +30,7 @@ import GCDKit
// MARK: - DataStack
@available(OSX, unavailable)
public extension DataStack {
// MARK: Public
@@ -40,6 +41,7 @@ public extension DataStack {
- parameter object: the `NSManagedObject` to observe changes from
- returns: a `ObjectMonitor` that monitors changes to `object`
*/
@warn_unused_result
public func monitorObject<T: NSManagedObject>(object: T) -> ObjectMonitor<T> {
CoreStore.assert(
@@ -59,7 +61,8 @@ public extension DataStack {
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
*/
@warn_unused_result
public func monitorList<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
return self.monitorList(from, fetchClauses)
@@ -71,7 +74,8 @@ public extension DataStack {
- parameter from: a `From` clause indicating the entity type
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
*/
@warn_unused_result
public func monitorList<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
CoreStore.assert(
@@ -98,7 +102,8 @@ public extension DataStack {
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
*/
@warn_unused_result
public func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
return self.monitorSectionedList(from, sectionBy, fetchClauses)
@@ -111,7 +116,8 @@ public extension DataStack {
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list
*/
*/
@warn_unused_result
public func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
CoreStore.assert(

File diff suppressed because it is too large Load Diff

View File

@@ -38,39 +38,68 @@ Implement the `ListObserver` protocol to observe changes to a list of `NSManaged
)
monitor.addObserver(self)
*/
@available(OSX, unavailable)
public protocol ListObserver: class {
/**
The `NSManagedObject` type for the observed list
*/
typealias EntityType: NSManagedObject
typealias ListEntityType: NSManagedObject
/**
Handles processing just before a change to the observed list occurs
- parameter monitor: the `ListMonitor` monitoring the list being observed
*/
func listMonitorWillChange(monitor: ListMonitor<EntityType>)
func listMonitorWillChange(monitor: ListMonitor<ListEntityType>)
/**
Handles processing right after a change to the observed list occurs
- parameter monitor: the `ListMonitor` monitoring the object being observed
*/
func listMonitorDidChange(monitor: ListMonitor<EntityType>)
func listMonitorDidChange(monitor: ListMonitor<ListEntityType>)
/**
This method is broadcast from within the `ListMonitor`'s `refetch(...)` 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.
- parameter monitor: the `ListMonitor` monitoring the object being observed
*/
func listMonitorWillRefetch(monitor: ListMonitor<ListEntityType>)
/**
After the `ListMonitor`'s `refetch(...)` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
- parameter monitor: the `ListMonitor` monitoring the object being observed
*/
func listMonitorDidRefetch(monitor: ListMonitor<ListEntityType>)
}
// MARK: - ListObserver (Default Implementations)
@available(OSX, unavailable)
public extension ListObserver {
/**
The default implementation does nothing.
*/
func listMonitorWillChange(monitor: ListMonitor<EntityType>) { }
func listMonitorWillChange(monitor: ListMonitor<ListEntityType>) { }
/**
The default implementation does nothing.
*/
func listMonitorDidChange(monitor: ListMonitor<EntityType>) { }
func listMonitorDidChange(monitor: ListMonitor<ListEntityType>) { }
/**
The default implementation does nothing.
*/
func listMonitorWillRefetch(monitor: ListMonitor<ListEntityType>) { }
/**
The default implementation does nothing.
*/
func listMonitorDidRefetch(monitor: ListMonitor<ListEntityType>) { }
}
@@ -85,6 +114,7 @@ Implement the `ListObjectObserver` protocol to observe detailed changes to a lis
)
monitor.addObserver(self)
*/
@available(OSX, unavailable)
public protocol ListObjectObserver: ListObserver {
/**
@@ -94,7 +124,7 @@ public protocol ListObjectObserver: ListObserver {
- parameter object: the entity type for the inserted object
- parameter indexPath: the new `NSIndexPath` for the inserted object
*/
func listMonitor(monitor: ListMonitor<EntityType>, didInsertObject object: EntityType, toIndexPath indexPath: NSIndexPath)
func listMonitor(monitor: ListMonitor<ListEntityType>, didInsertObject object: ListEntityType, toIndexPath indexPath: NSIndexPath)
/**
Notifies that an object was deleted from the specified `NSIndexPath` in the list
@@ -103,7 +133,7 @@ public protocol ListObjectObserver: ListObserver {
- parameter object: the entity type for the deleted object
- parameter indexPath: the `NSIndexPath` for the deleted object
*/
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteObject object: EntityType, fromIndexPath indexPath: NSIndexPath)
func listMonitor(monitor: ListMonitor<ListEntityType>, didDeleteObject object: ListEntityType, fromIndexPath indexPath: NSIndexPath)
/**
Notifies that an object at the specified `NSIndexPath` was updated
@@ -112,7 +142,7 @@ public protocol ListObjectObserver: ListObserver {
- parameter object: the entity type for the updated object
- parameter indexPath: the `NSIndexPath` for the updated object
*/
func listMonitor(monitor: ListMonitor<EntityType>, didUpdateObject object: EntityType, atIndexPath indexPath: NSIndexPath)
func listMonitor(monitor: ListMonitor<ListEntityType>, didUpdateObject object: ListEntityType, atIndexPath indexPath: NSIndexPath)
/**
Notifies that an object's index changed
@@ -122,30 +152,34 @@ public protocol ListObjectObserver: ListObserver {
- parameter fromIndexPath: the previous `NSIndexPath` for the moved object
- parameter toIndexPath: the new `NSIndexPath` for the moved object
*/
func listMonitor(monitor: ListMonitor<EntityType>, didMoveObject object: EntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
func listMonitor(monitor: ListMonitor<ListEntityType>, didMoveObject object: ListEntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
}
// MARK: - ListObjectObserver (Default Implementations)
@available(OSX, unavailable)
public extension ListObjectObserver {
/**
The default implementation does nothing.
*/
func listMonitor(monitor: ListMonitor<EntityType>, didInsertObject object: EntityType, toIndexPath indexPath: NSIndexPath) { }
func listMonitor(monitor: ListMonitor<ListEntityType>, didInsertObject object: ListEntityType, toIndexPath indexPath: NSIndexPath) { }
/**
The default implementation does nothing.
*/
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteObject object: EntityType, fromIndexPath indexPath: NSIndexPath) { }
func listMonitor(monitor: ListMonitor<ListEntityType>, didDeleteObject object: ListEntityType, fromIndexPath indexPath: NSIndexPath) { }
/**
The default implementation does nothing.
*/
func listMonitor(monitor: ListMonitor<EntityType>, didUpdateObject object: EntityType, atIndexPath indexPath: NSIndexPath) { }
func listMonitor(monitor: ListMonitor<ListEntityType>, didUpdateObject object: ListEntityType, atIndexPath indexPath: NSIndexPath) { }
/**
The default implementation does nothing.
*/
func listMonitor(monitor: ListMonitor<EntityType>, didMoveObject object: EntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { }
func listMonitor(monitor: ListMonitor<ListEntityType>, didMoveObject object: ListEntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { }
}
@@ -161,6 +195,7 @@ Implement the `ListSectionObserver` protocol to observe changes to a list's sect
)
monitor.addObserver(self)
*/
@available(OSX, unavailable)
public protocol ListSectionObserver: ListObjectObserver {
/**
@@ -169,8 +204,9 @@ public protocol ListSectionObserver: ListObjectObserver {
- parameter monitor: the `ListMonitor` monitoring the list being observed
- parameter sectionInfo: the `NSFetchedResultsSectionInfo` for the inserted section
- parameter sectionIndex: the new section index for the new section
*/
func listMonitor(monitor: ListMonitor<EntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
*/
@available(iOS 8.0, *)
func listMonitor(monitor: ListMonitor<ListEntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
/**
Notifies that a section was inserted at the specified index
@@ -178,19 +214,24 @@ public protocol ListSectionObserver: ListObjectObserver {
- parameter monitor: the `ListMonitor` monitoring the list being observed
- parameter sectionInfo: the `NSFetchedResultsSectionInfo` for the deleted section
- parameter sectionIndex: the previous section index for the deleted section
*/
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
*/
@available(iOS 8.0, *)
func listMonitor(monitor: ListMonitor<ListEntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
}
// MARK: - ListSectionObserver (Default Implementations)
@available(OSX, unavailable)
public extension ListSectionObserver {
/**
The default implementation does nothing.
*/
func listMonitor(monitor: ListMonitor<EntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { }
func listMonitor(monitor: ListMonitor<ListEntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { }
/**
The default implementation does nothing.
*/
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { }
func listMonitor(monitor: ListMonitor<ListEntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { }
}

View File

@@ -28,20 +28,6 @@ import CoreData
import GCDKit
private let ObjectMonitorWillChangeObjectNotification = "ObjectMonitorWillChangeObjectNotification"
private let ObjectMonitorDidDeleteObjectNotification = "ObjectMonitorDidDeleteObjectNotification"
private let ObjectMonitorDidUpdateObjectNotification = "ObjectMonitorDidUpdateObjectNotification"
private let UserInfoKeyObject = "UserInfoKeyObject"
private struct NotificationKey {
static var willChangeObject: Void?
static var didDeleteObject: Void?
static var didUpdateObject: Void?
}
// MARK: - ObjectMonitor
/**
@@ -54,6 +40,7 @@ The created `ObjectMonitor` instance needs to be held on (retained) for as long
Observers registered via `addObserver(_:)` are not retained. `ObjectMonitor` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
*/
@available(OSX, unavailable)
public final class ObjectMonitor<T: NSManagedObject> {
// MARK: Public
@@ -85,7 +72,7 @@ public final class ObjectMonitor<T: NSManagedObject> {
- parameter observer: an `ObjectObserver` to send change notifications to
*/
public func addObserver<U: ObjectObserver where U.EntityType == T>(observer: U) {
public func addObserver<U: ObjectObserver where U.ObjectEntityType == T>(observer: U) {
CoreStore.assert(
NSThread.isMainThread(),
@@ -95,56 +82,60 @@ public final class ObjectMonitor<T: NSManagedObject> {
self.removeObserver(observer)
self.registerChangeNotification(
&NotificationKey.willChangeObject,
&self.willChangeObjectKey,
name: ObjectMonitorWillChangeObjectNotification,
toObserver: observer,
callback: { [weak observer] (monitor) -> Void in
if let object = monitor.object, let observer = observer {
guard let object = monitor.object, let observer = observer else {
observer.objectMonitor(monitor, willUpdateObject: object)
return
}
observer.objectMonitor(monitor, willUpdateObject: object)
}
)
self.registerObjectNotification(
&NotificationKey.didDeleteObject,
&self.didDeleteObjectKey,
name: ObjectMonitorDidDeleteObjectNotification,
toObserver: observer,
callback: { [weak observer] (monitor, object) -> Void in
if let observer = observer {
guard let observer = observer else {
observer.objectMonitor(monitor, didDeleteObject: object)
return
}
observer.objectMonitor(monitor, didDeleteObject: object)
}
)
self.registerObjectNotification(
&NotificationKey.didUpdateObject,
&self.didUpdateObjectKey,
name: ObjectMonitorDidUpdateObjectNotification,
toObserver: observer,
callback: { [weak self, weak observer] (monitor, object) -> Void in
if let strongSelf = self, let observer = observer {
guard let strongSelf = self, let observer = observer else {
let previousCommitedAttributes = strongSelf.lastCommittedAttributes
let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [String: NSObject]
let changedKeys = currentCommitedAttributes.keys.reduce(Set<String>()) { (var changedKeys, key) -> Set<String> in
if previousCommitedAttributes[key] != currentCommitedAttributes[key] {
changedKeys.insert(key)
}
return changedKeys
}
strongSelf.lastCommittedAttributes = currentCommitedAttributes
observer.objectMonitor(
monitor,
didUpdateObject: object,
changedPersistentKeys: changedKeys
)
return
}
let previousCommitedAttributes = strongSelf.lastCommittedAttributes
let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [String: NSObject]
var changedKeys = Set<String>()
for key in currentCommitedAttributes.keys {
if previousCommitedAttributes[key] != currentCommitedAttributes[key] {
changedKeys.insert(key)
}
}
strongSelf.lastCommittedAttributes = currentCommitedAttributes
observer.objectMonitor(
monitor,
didUpdateObject: object,
changedPersistentKeys: changedKeys
)
}
)
}
@@ -156,7 +147,7 @@ public final class ObjectMonitor<T: NSManagedObject> {
- parameter observer: an `ObjectObserver` to unregister notifications to
*/
public func removeObserver<U: ObjectObserver where U.EntityType == T>(observer: U) {
public func removeObserver<U: ObjectObserver where U.ObjectEntityType == T>(observer: U) {
CoreStore.assert(
NSThread.isMainThread(),
@@ -164,9 +155,9 @@ public final class ObjectMonitor<T: NSManagedObject> {
)
let nilValue: AnyObject? = nil
setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.willChangeObject, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.didDeleteObject, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &NotificationKey.didUpdateObject, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &self.willChangeObjectKey, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &self.didDeleteObjectKey, inObject: observer)
setAssociatedRetainedObject(nilValue, forKey: &self.didUpdateObjectKey, inObject: observer)
}
@@ -182,6 +173,8 @@ public final class ObjectMonitor<T: NSManagedObject> {
fetchRequest.fetchLimit = 0
fetchRequest.resultType = .ManagedObjectResultType
fetchRequest.sortDescriptors = []
fetchRequest.includesPendingChanges = false
fetchRequest.shouldRefreshRefetchedObjects = true
let originalObjectID = object.objectID
Where("SELF", isEqualTo: originalObjectID).applyToFetchRequest(fetchRequest)
@@ -195,7 +188,6 @@ public final class ObjectMonitor<T: NSManagedObject> {
let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate()
self.originalObjectID = originalObjectID
self.fetchedResultsController = fetchedResultsController
self.fetchedResultsControllerDelegate = fetchedResultsControllerDelegate
self.parentStack = dataStack
@@ -207,15 +199,23 @@ public final class ObjectMonitor<T: NSManagedObject> {
self.lastCommittedAttributes = (self.object?.committedValuesForKeys(nil) as? [String: NSObject]) ?? [:]
}
deinit {
self.fetchedResultsControllerDelegate.fetchedResultsController = nil
}
// MARK: Private
private let originalObjectID: NSManagedObjectID
private let fetchedResultsController: NSFetchedResultsController
private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
private var lastCommittedAttributes = [String: NSObject]()
private weak var parentStack: DataStack?
private var willChangeObjectKey: Void?
private var didDeleteObjectKey: Void?
private var didUpdateObjectKey: Void?
private func registerChangeNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (monitor: ObjectMonitor<T>) -> Void) {
setAssociatedRetainedObject(
@@ -224,10 +224,11 @@ public final class ObjectMonitor<T: NSManagedObject> {
object: self,
closure: { [weak self] (note) -> Void in
if let strongSelf = self {
guard let strongSelf = self else {
callback(monitor: strongSelf)
return
}
callback(monitor: strongSelf)
}
),
forKey: notificationKey,
@@ -243,15 +244,13 @@ public final class ObjectMonitor<T: NSManagedObject> {
object: self,
closure: { [weak self] (note) -> Void in
if let strongSelf = self,
guard let strongSelf = self,
let userInfo = note.userInfo,
let object = userInfo[UserInfoKeyObject] as? T {
let object = userInfo[UserInfoKeyObject] as? T else {
callback(
monitor: strongSelf,
object: object
)
return
}
callback(monitor: strongSelf, object: object)
}
),
forKey: notificationKey,
@@ -263,21 +262,34 @@ public final class ObjectMonitor<T: NSManagedObject> {
// MARK: - ObjectMonitor: Equatable
@available(OSX, unavailable)
public func ==<T: NSManagedObject>(lhs: ObjectMonitor<T>, rhs: ObjectMonitor<T>) -> Bool {
return lhs === rhs
}
@available(OSX, unavailable)
extension ObjectMonitor: Equatable { }
// MARK: - ObjectMonitor: FetchedResultsControllerHandler
@available(OSX, unavailable)
extension ObjectMonitor: FetchedResultsControllerHandler {
// MARK: FetchedResultsControllerHandler
private func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
internal func controllerWillChangeContent(controller: NSFetchedResultsController) {
NSNotificationCenter.defaultCenter().postNotificationName(
ObjectMonitorWillChangeObjectNotification,
object: self
)
}
internal func controllerDidChangeContent(controller: NSFetchedResultsController) { }
internal func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
@@ -288,7 +300,7 @@ extension ObjectMonitor: FetchedResultsControllerHandler {
userInfo: [UserInfoKeyObject: anObject]
)
case .Update, .Move where indexPath == newIndexPath:
case .Update:
NSNotificationCenter.defaultCenter().postNotificationName(
ObjectMonitorDidUpdateObjectNotification,
object: self,
@@ -300,57 +312,18 @@ extension ObjectMonitor: FetchedResultsControllerHandler {
}
}
private func controllerWillChangeContent(controller: NSFetchedResultsController) {
internal func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { }
internal func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String? {
NSNotificationCenter.defaultCenter().postNotificationName(
ObjectMonitorWillChangeObjectNotification,
object: self
)
return sectionName
}
}
// MARK: - FetchedResultsControllerHandler
private let ObjectMonitorWillChangeObjectNotification = "ObjectMonitorWillChangeObjectNotification"
private let ObjectMonitorDidDeleteObjectNotification = "ObjectMonitorDidDeleteObjectNotification"
private let ObjectMonitorDidUpdateObjectNotification = "ObjectMonitorDidUpdateObjectNotification"
private protocol FetchedResultsControllerHandler: class {
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)
func controllerWillChangeContent(controller: NSFetchedResultsController)
}
private let UserInfoKeyObject = "UserInfoKeyObject"
// MARK: - FetchedResultsControllerDelegate
private final class FetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate {
// MARK: NSFetchedResultsControllerDelegate
@objc dynamic func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.handler?.controllerWillChangeContent(controller)
}
@objc dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
self.handler?.controller(controller, didChangeObject: anObject, atIndexPath: indexPath, forChangeType: type, newIndexPath: newIndexPath)
}
// MARK: Private
weak var handler: FetchedResultsControllerHandler?
weak var fetchedResultsController: NSFetchedResultsController? {
didSet {
oldValue?.delegate = nil
self.fetchedResultsController?.delegate = self
}
}
deinit {
self.fetchedResultsController?.delegate = nil
}
}

View File

@@ -35,12 +35,13 @@ Implement the `ObjectObserver` protocol to observe changes to a single `NSManage
let monitor = CoreStore.monitorObject(object)
monitor.addObserver(self)
*/
@available(OSX, unavailable)
public protocol ObjectObserver: class {
/**
The `NSManagedObject` type for the observed object
*/
typealias EntityType: NSManagedObject
typealias ObjectEntityType: NSManagedObject
/**
Handles processing just before a change to the observed `object` occurs
@@ -48,7 +49,7 @@ public protocol ObjectObserver: class {
- parameter monitor: the `ObjectMonitor` monitoring the object being observed
- parameter object: the `NSManagedObject` instance being observed
*/
func objectMonitor(monitor: ObjectMonitor<EntityType>, willUpdateObject object: EntityType)
func objectMonitor(monitor: ObjectMonitor<ObjectEntityType>, willUpdateObject object: ObjectEntityType)
/**
Handles processing right after a change to the observed `object` occurs
@@ -57,7 +58,7 @@ public protocol ObjectObserver: class {
- parameter object: the `NSManagedObject` instance being observed
- parameter changedPersistentKeys: a `Set` 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.
*/
func objectMonitor(monitor: ObjectMonitor<EntityType>, didUpdateObject object: EntityType, changedPersistentKeys: Set<KeyPath>)
func objectMonitor(monitor: ObjectMonitor<ObjectEntityType>, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set<KeyPath>)
/**
Handles processing right after `object` is deleted
@@ -65,24 +66,27 @@ public protocol ObjectObserver: class {
- parameter monitor: the `ObjectMonitor` monitoring the object being observed
- parameter object: the `NSManagedObject` instance being observed
*/
func objectMonitor(monitor: ObjectMonitor<EntityType>, didDeleteObject object: EntityType)
func objectMonitor(monitor: ObjectMonitor<ObjectEntityType>, didDeleteObject object: ObjectEntityType)
}
// MARK: - ObjectObserver (Default Implementations)
@available(OSX, unavailable)
public extension ObjectObserver {
/**
The default implementation does nothing.
*/
func objectMonitor(monitor: ObjectMonitor<EntityType>, willUpdateObject object: EntityType) { }
func objectMonitor(monitor: ObjectMonitor<ObjectEntityType>, willUpdateObject object: ObjectEntityType) { }
/**
The default implementation does nothing.
*/
func objectMonitor(monitor: ObjectMonitor<EntityType>, didUpdateObject object: EntityType, changedPersistentKeys: Set<KeyPath>) { }
func objectMonitor(monitor: ObjectMonitor<ObjectEntityType>, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set<KeyPath>) { }
/**
The default implementation does nothing.
*/
func objectMonitor(monitor: ObjectMonitor<EntityType>, didDeleteObject object: EntityType) { }
func objectMonitor(monitor: ObjectMonitor<ObjectEntityType>, didDeleteObject object: ObjectEntityType) { }
}

View File

@@ -38,6 +38,7 @@ The `SectionBy` clause indicates the key path to use to group the `ListMonitor`
OrderBy(.Ascending("lastName"))
)
*/
@available(OSX, unavailable)
public struct SectionBy {
// MARK: Public

View File

@@ -54,14 +54,15 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
)
self.isCommitted = true
let semaphore = GCDSemaphore(0)
let group = GCDGroup()
group.enter()
self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
self.result = result
completion(result: result)
semaphore.signal()
group.leave()
}
semaphore.wait()
group.wait()
}
/**
@@ -112,6 +113,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public override func edit<T: NSManagedObject>(object: T?) -> T? {
CoreStore.assert(
@@ -129,6 +131,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public override func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert(
@@ -168,7 +171,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
"Attempted to delete an entities from an already committed \(typeName(self))."
)
super.delete([object1, object2] + objects)
super.delete(([object1, object2] + objects).flatMap { $0 })
}
/**
@@ -176,7 +179,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter objects: the `NSManagedObject`s type to be deleted
*/
public override func delete(objects: [NSManagedObject?]) {
public override func delete<S: SequenceType where S.Generator.Element: NSManagedObject>(objects: S) {
CoreStore.assert(
!self.isCommitted,

View File

@@ -104,14 +104,18 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public func edit<T: NSManagedObject>(object: T?) -> T? {
CoreStore.assert(
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
"Attempted to update an entity of type \(typeName(object)) outside its designated queue."
)
return object?.inContext(self.context)
guard let object = object else {
return nil
}
return self.context.fetchExisting(object)
}
/**
@@ -121,6 +125,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert(
@@ -132,8 +137,7 @@ public /*abstract*/ class BaseDataTransaction {
|| (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName,
"Attempted to update an entity of type \(typeName(T)) but the specified persistent store do not match the `NSManagedObjectID`."
)
return (into.entityClass as! NSManagedObject.Type).inContext(self.context, withObjectID: objectID) as? T
return self.fetchExisting(objectID) as? T
}
/**
@@ -147,8 +151,11 @@ public /*abstract*/ class BaseDataTransaction {
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
"Attempted to delete an entity outside its designated queue."
)
object?.inContext(self.context)?.deleteFromContext()
guard let object = object else {
return
}
self.context.fetchExisting(object)?.deleteFromContext()
}
/**
@@ -160,7 +167,7 @@ public /*abstract*/ class BaseDataTransaction {
*/
public func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
self.delete([object1, object2] + objects)
self.delete(([object1, object2] + objects).flatMap { $0 })
}
/**
@@ -168,7 +175,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter objects: the `NSManagedObject`s to be deleted
*/
public func delete(objects: [NSManagedObject?]) {
public func delete<S: SequenceType where S.Generator.Element: NSManagedObject>(objects: S) {
CoreStore.assert(
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
@@ -176,10 +183,7 @@ public /*abstract*/ class BaseDataTransaction {
)
let context = self.context
for object in objects {
object?.inContext(context)?.deleteFromContext()
}
objects.forEach { context.fetchExisting($0)?.deleteFromContext() }
}
// MARK: Saving changes

View File

@@ -54,12 +54,20 @@ public extension CoreStore {
}
/**
Using the `defaultStack`, begins a non-contiguous transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms. A detached transaction object should typically be only used from the main queue.
Using the `defaultStack`, begins a non-contiguous transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms. An unsafe transaction object should typically be only used from the main queue.
- returns: a `DetachedDataTransaction` instance where creates, updates, and deletes can be made.
- returns: a `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
public static func beginDetached() -> DetachedDataTransaction {
@warn_unused_result
public static func beginUnsafe() -> UnsafeDataTransaction {
return self.defaultStack.beginDetached()
return self.defaultStack.beginUnsafe()
}
@available(*, deprecated=1.3.1, renamed="beginUnsafe")
@warn_unused_result
public static func beginDetached() -> UnsafeDataTransaction {
return self.beginUnsafe()
}
}

View File

@@ -64,16 +64,24 @@ public extension DataStack {
/**
Begins a non-contiguous transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms.
- returns: a `DetachedDataTransaction` instance where creates, updates, and deletes can be made.
- returns: a `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
public func beginDetached() -> DetachedDataTransaction {
@warn_unused_result
public func beginUnsafe() -> UnsafeDataTransaction {
return DetachedDataTransaction(
return UnsafeDataTransaction(
mainContext: self.rootSavingContext,
queue: .createSerial(
"com.coreStore.dataStack.detachedTransactionQueue",
"com.coreStore.dataStack.unsafeTransactionQueue",
targetQueue: .UserInitiated
)
)
}
@available(*, deprecated=1.3.1, renamed="beginUnsafe")
@warn_unused_result
public func beginDetached() -> UnsafeDataTransaction {
return self.beginUnsafe()
}
}

View File

@@ -36,7 +36,7 @@ let person = transaction.create(Into(MyPersonEntity))
For cases where multiple `NSPersistentStore`s contain the same entity, the destination configuration's name needs to be specified as well:
let person = transaction.create(Into<MyPersonEntity>("Configuration1"))
let person = transaction.create(Into<MyPersonEntity>("Configuration1"))
This helps the `NSManagedObjectContext` to determine which
*/
@@ -48,7 +48,7 @@ public struct Into<T: NSManagedObject> {
Initializes an `Into` clause.
Sample Usage:
let person = transaction.create(Into<MyPersonEntity>())
let person = transaction.create(Into<MyPersonEntity>())
*/
public init(){

View File

@@ -103,6 +103,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public override func edit<T: NSManagedObject>(object: T?) -> T? {
CoreStore.assert(
@@ -120,6 +121,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public override func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert(
@@ -159,7 +161,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
"Attempted to delete an entities from an already committed \(typeName(self))."
)
super.delete([object1, object2] + objects)
super.delete(([object1, object2] + objects).flatMap { $0 })
}
/**
@@ -167,7 +169,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter objects: the `NSManagedObject`s to be deleted
*/
public override func delete(objects: [NSManagedObject?]) {
public override func delete<S: SequenceType where S.Generator.Element: NSManagedObject>(objects: S) {
CoreStore.assert(
!self.isCommitted,

View File

@@ -1,5 +1,5 @@
//
// DetachedDataTransaction.swift
// UnsafeDataTransaction.swift
// CoreStore
//
// Copyright (c) 2015 John Rommel Estropia
@@ -24,20 +24,25 @@
//
import Foundation
import CoreData
import GCDKit
// MARK: - DetachedDataTransaction
@available(*, deprecated=1.3.1, renamed="UnsafeDataTransaction")
public typealias DetachedDataTransaction = UnsafeDataTransaction
// MARK: - UnsafeDataTransaction
/**
The `DetachedDataTransaction` provides an interface for non-contiguous `NSManagedObject` creates, updates, and deletes. This is useful for making temporary changes, such as partially filled forms. A detached transaction object should typically be only used from the main queue.
The `UnsafeDataTransaction` provides an interface for non-contiguous `NSManagedObject` creates, updates, and deletes. This is useful for making temporary changes, such as partially filled forms. An unsafe transaction object should typically be only used from the main queue.
*/
public final class DetachedDataTransaction: BaseDataTransaction {
public final class UnsafeDataTransaction: BaseDataTransaction {
// MARK: Public
/**
Saves the transaction changes asynchronously. For a `DetachedDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread.
Saves the transaction changes asynchronously. For a `UnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread.
- parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block.
*/
@@ -53,28 +58,36 @@ public final class DetachedDataTransaction: BaseDataTransaction {
/**
Begins a child transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms.
- returns: a `DetachedDataTransaction` instance where creates, updates, and deletes can be made.
- returns: a `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
public func beginDetached() -> DetachedDataTransaction {
@warn_unused_result
public func beginUnsafe() -> UnsafeDataTransaction {
return DetachedDataTransaction(
return UnsafeDataTransaction(
mainContext: self.context,
queue: self.transactionQueue
)
}
/**
Returns the `NSManagedObjectContext` for this detached transaction. Use only for cases where external frameworks need an `NSManagedObjectContext` instance to work with.
Returns the `NSManagedObjectContext` for this unsafe transaction. Use only for cases where external frameworks need an `NSManagedObjectContext` instance to work with.
Note that it is the developer's responsibility to ensure the following:
- that the `DetachedDataTransaction` that owns this context should be strongly referenced and prevented from being deallocated during the context's lifetime
- that all saves will be done either through the `DetachedDataTransaction`'s `commit(...)` method, or by calling `save()` manually on the context, its parent, and all other ancestor contexts if there are any.
- that the `UnsafeDataTransaction` that owns this context should be strongly referenced and prevented from being deallocated during the context's lifetime
- that all saves will be done either through the `UnsafeDataTransaction`'s `commit(...)` method, or by calling `save()` manually on the context, its parent, and all other ancestor contexts if there are any.
*/
public var internalContext: NSManagedObjectContext {
return self.context
}
@available(*, deprecated=1.3.1, renamed="beginUnsafe")
@warn_unused_result
public func beginDetached() -> UnsafeDataTransaction {
return self.beginUnsafe()
}
// MARK: Internal

View File

@@ -43,9 +43,17 @@ public extension CoreStore {
/**
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
*/
public static var entitiesByName: [String: NSManagedObject.Type] {
public static var entityTypesByName: [String: NSManagedObject.Type] {
return self.defaultStack.entitiesByName
return self.defaultStack.entityTypesByName
}
/**
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model.
*/
public static func entityDescriptionForType(type: NSManagedObject.Type) -> NSEntityDescription? {
return self.defaultStack.entityDescriptionForType(type)
}
/**

View File

@@ -84,9 +84,20 @@ public final class DataStack {
/**
Returns the entity name-to-class type mapping from the `DataStack`'s model.
*/
public var entitiesByName: [String: NSManagedObject.Type] {
public var entityTypesByName: [String: NSManagedObject.Type] {
return self.model.entityMapping()
return self.model.entityTypesMapping()
}
/**
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass.
*/
public func entityDescriptionForType(type: NSManagedObject.Type) -> NSEntityDescription? {
return NSEntityDescription.entityForName(
self.model.entityNameForClass(type),
inManagedObjectContext: self.mainContext
)
}
/**
@@ -178,34 +189,31 @@ public final class DataStack {
let coordinator = self.coordinator;
if let store = coordinator.persistentStoreForURL(fileURL) {
if store.type == NSSQLiteStoreType
&& store.configurationName == (configuration ?? Into.defaultConfigurationName) {
guard store.type == NSSQLiteStoreType
&& store.configurationName == (configuration ?? Into.defaultConfigurationName) else {
return store
let error = NSError(coreStoreErrorCode: .DifferentPersistentStoreExistsAtURL)
CoreStore.handleError(
error,
"Failed to add SQLite \(typeName(NSPersistentStore)) at \"\(fileURL)\" because a different \(typeName(NSPersistentStore)) at that URL already exists."
)
throw error
}
let error = NSError(coreStoreErrorCode: .DifferentPersistentStoreExistsAtURL)
CoreStore.handleError(
error,
"Failed to add SQLite \(typeName(NSPersistentStore)) at \"\(fileURL)\" because a different \(typeName(NSPersistentStore)) at that URL already exists."
)
throw error
return store
}
let fileManager = NSFileManager.defaultManager()
do {
try fileManager.createDirectoryAtURL(
fileURL.URLByDeletingLastPathComponent!,
withIntermediateDirectories: true,
attributes: nil
)
}
catch _ { }
_ = try? fileManager.createDirectoryAtURL(
fileURL.URLByDeletingLastPathComponent!,
withIntermediateDirectories: true,
attributes: nil
)
var store: NSPersistentStore?
var storeError: NSError?
let options = self.optionsForSQLiteStore()
coordinator.performBlockAndWait {
do {
@@ -214,7 +222,7 @@ public final class DataStack {
NSSQLiteStoreType,
configuration: configuration,
URL: fileURL,
options: [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
options: options
)
}
catch {
@@ -286,6 +294,11 @@ public final class DataStack {
return migrationQueue
}()
internal func optionsForSQLiteStore() -> [String: AnyObject] {
return [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
}
internal func entityNameForEntityClass(entityClass: AnyClass) -> String? {
return self.model.entityNameForClass(entityClass)
@@ -366,11 +379,7 @@ public final class DataStack {
for store in self.coordinator.persistentStores {
do {
try self.coordinator.removePersistentStore(store)
}
catch _ { }
_ = try? self.coordinator.removePersistentStore(store)
}
}
}

View File

@@ -48,6 +48,13 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
B56321C51BD65965006C9394 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B583A9141AF5F4F3001F76AF /* CoreStore.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = B563216F1BD65082006C9394;
remoteInfo = "CoreStore watchOS";
};
B583A91A1AF5F4F4001F76AF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B583A9141AF5F4F3001F76AF /* CoreStore.xcodeproj */;
@@ -279,7 +286,8 @@
isa = PBXGroup;
children = (
B583A91B1AF5F4F4001F76AF /* CoreStore.framework */,
B583A91D1AF5F4F4001F76AF /* CoreStoreTests.xctest */,
B583A91D1AF5F4F4001F76AF /* CoreStoreTests iOS.xctest */,
B56321C61BD65965006C9394 /* CoreStore.framework */,
);
name = Products;
sourceTree = "<group>";
@@ -347,6 +355,13 @@
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
B56321C61BD65965006C9394 /* CoreStore.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = CoreStore.framework;
remoteRef = B56321C51BD65965006C9394 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B583A91B1AF5F4F4001F76AF /* CoreStore.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
@@ -354,10 +369,10 @@
remoteRef = B583A91A1AF5F4F4001F76AF /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B583A91D1AF5F4F4001F76AF /* CoreStoreTests.xctest */ = {
B583A91D1AF5F4F4001F76AF /* CoreStoreTests iOS.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = CoreStoreTests.xctest;
path = "CoreStoreTests iOS.xctest";
remoteRef = B583A91C1AF5F4F4001F76AF /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};

View File

@@ -12,6 +12,41 @@ import CoreStore
private struct Static {
enum Filter: String {
case All = "All Colors"
case Light = "Light Colors"
case Dark = "Dark Colors"
func next() -> Filter {
switch self {
case All: return .Light
case Light: return .Dark
case Dark: return .All
}
}
func whereClause() -> Where {
switch self {
case .All: return Where(true)
case .Light: return Where("brightness >= 0.9")
case .Dark: return Where("brightness <= 0.4")
}
}
}
static var filter = Filter.All {
didSet {
self.palettes.refetch(self.filter.whereClause())
}
}
static let palettes: ListMonitor<Palette> = {
try! CoreStore.addSQLiteStoreAndWait(
@@ -47,7 +82,8 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
super.viewDidLoad()
self.navigationItem.leftBarButtonItems = [
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItems = [
self.editButtonItem(),
UIBarButtonItem(
barButtonSystemItem: .Trash,
@@ -55,13 +91,26 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
action: "resetBarButtonItemTouched:"
)
]
self.navigationItem.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .Add,
let filterBarButton = UIBarButtonItem(
title: Static.filter.rawValue,
style: .Plain,
target: self,
action: "addBarButtonItemTouched:"
action: "filterBarButtonItemTouched:"
)
navigationItem.rightBarButtonItems = [
UIBarButtonItem(
barButtonSystemItem: .Add,
target: self,
action: "addBarButtonItemTouched:"
),
filterBarButton
]
self.filterBarButton = filterBarButton
Static.palettes.addObserver(self)
self.setTableEnabled(!Static.palettes.isPendingRefetch)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
@@ -150,6 +199,18 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
self.tableView.endUpdates()
}
func listMonitorWillRefetch(monitor: ListMonitor<Palette>) {
self.setTableEnabled(false)
}
func listMonitorDidRefetch(monitor: ListMonitor<Palette>) {
self.filterBarButton?.title = Static.filter.rawValue
self.tableView.reloadData()
self.setTableEnabled(true)
}
// MARK: ListObjectObserver
@@ -195,6 +256,8 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
// MARK: Private
private var filterBarButton: UIBarButtonItem?
@IBAction private dynamic func resetBarButtonItemTouched(sender: AnyObject?) {
CoreStore.beginAsynchronous { (transaction) -> Void in
@@ -204,6 +267,11 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
}
}
@IBAction private dynamic func filterBarButtonItemTouched(sender: AnyObject?) {
Static.filter = Static.filter.next()
}
@IBAction private dynamic func addBarButtonItemTouched(sender: AnyObject?) {
CoreStore.beginAsynchronous { (transaction) -> Void in
@@ -214,5 +282,23 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
transaction.commit()
}
}
private func setTableEnabled(enabled: Bool) {
UIView.animateWithDuration(
0.2,
delay: 0,
options: .BeginFromCurrentState,
animations: { () -> Void in
if let tableView = self.tableView {
tableView.alpha = enabled ? 1.0 : 0.5
tableView.userInteractionEnabled = enabled
}
},
completion: nil
)
}
}

View File

@@ -22,6 +22,11 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
}
set {
guard self.monitor?.object != newValue else {
return
}
if let palette = newValue {
self.monitor = CoreStore.monitorObject(palette)

View File

@@ -285,7 +285,7 @@ class MigrationsDemoViewController: UIViewController {
}
self.titleLabel?.text = organismType
self.organismLabel?.text = "\n".join(lines)
self.organismLabel?.text = lines.joinWithSeparator("\n")
self.progressView?.progress = 0
self.headerContainer?.setNeedsLayout()

View File

@@ -78,7 +78,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
let alert = UIAlertController(
title: "Transactions Demo",
message: "This demo shows how to use the 3 types of transactions to save updates: synchronous, asynchronous, and detached.\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
)
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
@@ -159,13 +159,14 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
if let mapView = self.mapView, let gesture = sender as? UILongPressGestureRecognizer where gesture.state == .Began {
let coordinate = mapView.convertPoint(
gesture.locationInView(mapView),
toCoordinateFromView: mapView
)
CoreStore.beginAsynchronous { (transaction) -> Void in
let place = transaction.edit(Static.placeController.object)
place?.coordinate = mapView.convertPoint(
gesture.locationInView(mapView),
toCoordinateFromView: mapView
)
place?.coordinate = coordinate
transaction.commit { (_) -> Void in }
}
}
@@ -183,7 +184,7 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec
func geocodePlace(place: Place) {
let transaction = CoreStore.beginDetached()
let transaction = CoreStore.beginUnsafe()
self.geocoder?.cancelGeocode()

View File

@@ -23,7 +23,6 @@
// SOFTWARE.
//
import UIKit
import XCTest
@testable
@@ -103,7 +102,7 @@ class CoreStoreTests: XCTestCase {
XCTFail(error.description)
}
let detachedTransaction = CoreStore.beginDetached()
let unsafeTransaction = CoreStore.beginUnsafe()
let createExpectation = self.expectationWithDescription("Entity creation")
CoreStore.beginAsynchronous { (transaction) -> Void in
@@ -182,7 +181,7 @@ class CoreStoreTests: XCTestCase {
)
XCTAssertNil(objs4test, "objs4test == nil")
let objs5test = detachedTransaction.fetchCount(From(TestEntity2))
let objs5test = unsafeTransaction.fetchCount(From(TestEntity2))
XCTAssertTrue(objs5test == 3, "objs5test == 3")
XCTAssertTrue(NSThread.isMainThread(), "NSThread.isMainThread()")
@@ -289,15 +288,15 @@ class CoreStoreTests: XCTestCase {
XCTAssertNotNil(objs2, "objs2 != nil")
XCTAssertTrue(objs2?.count == 1, "objs2?.count == 1")
let detachedExpectation = self.expectationWithDescription("Query creation")
let unsafeExpectation = self.expectationWithDescription("Query creation")
let obj5 = detachedTransaction.create(Into<TestEntity1>("Config1"))
let obj5 = unsafeTransaction.create(Into<TestEntity1>("Config1"))
obj5.testEntityID = 5
obj5.testString = "hihihi"
obj5.testNumber = 70
obj5.testDate = NSDate()
detachedTransaction.commit { (result) -> Void in
unsafeTransaction.commit { (result) -> Void in
XCTAssertTrue(NSThread.isMainThread(), "NSThread.isMainThread()")
switch result {
@@ -322,13 +321,13 @@ class CoreStoreTests: XCTestCase {
)
XCTAssertTrue(count == 1, "count == 1 (actual: \(count))")
let obj6 = detachedTransaction.create(Into<TestEntity1>())
let obj6 = unsafeTransaction.create(Into<TestEntity1>())
obj6.testEntityID = 6
obj6.testString = "huehuehue"
obj6.testNumber = 130
obj6.testDate = NSDate()
detachedTransaction.commit { (result) -> Void in
unsafeTransaction.commit { (result) -> Void in
XCTAssertTrue(NSThread.isMainThread(), "NSThread.isMainThread()")
switch result {
@@ -358,7 +357,7 @@ class CoreStoreTests: XCTestCase {
)
XCTAssertTrue(count2 == 0, "count == 0 (actual: \(count2))")
detachedExpectation.fulfill()
unsafeExpectation.fulfill()
case .Failure(let error):
XCTFail(error.description)
@@ -377,8 +376,9 @@ class CoreStoreTests: XCTestCase {
do {
try NSFileManager.defaultManager().removeItemAtURL(
NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask).first!
let fileManager = NSFileManager.defaultManager()
try fileManager.removeItemAtURL(
fileManager.URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask).first!
)
}
catch _ { }

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="7701" systemVersion="14D136" minimumToolsVersion="Xcode 4.3" macOSVersion="Automatic" iOSVersion="Automatic">
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="9057" systemVersion="15B42" minimumToolsVersion="Xcode 4.3">
<entity name="TestEntity1AAA" representedClassName="CoreStoreTests.TestEntity1" syncable="YES">
<attribute name="testDate" optional="YES" attributeType="Date" syncable="YES"/>
<attribute name="testEntityID" attributeType="Integer 64" syncable="YES"/>

244
README.md
View File

@@ -5,7 +5,7 @@
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
Unleashing the real power of Core Data with the elegance and safety of Swift
(Swift 2.0, iOS 8+)
* Swift 2.1 (XCode 7.1), iOS 8+/OSX 10.10+ (or try out the [iOS 7 branch](https://github.com/JohnEstropia/CoreStore/tree/ios7_support_alpha))
[Click here for a wiki version of this README](https://github.com/JohnEstropia/CoreStore/wiki)
@@ -14,7 +14,7 @@ Unleashing the real power of Core Data with the elegance and safety of Swift
## What CoreStore does better:
- Heavily supports multiple persistent stores per data stack, just the way *.xcdatamodeld* files are designed to. CoreStore will also manage one data stack by default, but you can create and manage as many as you need.
- **New in 1.0.0:** Incremental Migrations! Just tell the data stack the sequence of model versions and CoreStore will automatically use incremental migrations if needed on stores added to that stack.
- Incremental Migrations! Just tell the data stack the sequence of model versions and CoreStore will automatically use incremental migrations if needed on stores added to that stack.
- Ability to plug-in your own logging framework
- Gets around a limitation with other Core Data wrappers where the entity name should be the same as the `NSManagedObject` subclass name. CoreStore loads entity-to-class mappings from the managed object model file, so you are free to name them independently.
- Provides type-safe, easy to configure observers to replace `NSFetchedResultsController` and KVO
@@ -22,6 +22,7 @@ Unleashing the real power of Core Data with the elegance and safety of Swift
- Makes it hard to fall into common concurrency mistakes. All `NSManagedObjectContext` tasks are encapsulated into safer, higher-level abstractions without sacrificing flexibility and customizability.
- Exposes clean and convenient API designed around Swifts code elegance and type safety.
- Documentation! No magic here; all public classes, functions, properties, etc. have detailed Apple Docs. This README also introduces a lot of concepts and explains a lot of CoreStore's behavior.
- **New in 1.3.0:** Efficient importing utilities!
**CoreStore's goal is not to expose shorter, magical syntax, but to provide an API that focuses on readability, consistency, and safety.**
@@ -40,10 +41,12 @@ Unleashing the real power of Core Data with the elegance and safety of Swift
- [Transaction types](#transaction-types)
- [Asynchronous transactions](#asynchronous-transactions)
- [Synchronous transactions](#synchronous-transactions)
- [Detached transactions](#detached-transactions)
- [Unsafe transactions](#unsafe-transactions)
- [Creating objects](#creating-objects)
- [Updating objects](#updating-objects)
- [Deleting objects](#deleting-objects)
- [Passing objects safely](#passing-objects-safely)
- [Importing data](#importing-data)
- [Fetching and querying](#fetching-and-querying)
- [`From` clause](#from-clause)
- [Fetching](#fetching)
@@ -54,7 +57,7 @@ Unleashing the real power of Core Data with the elegance and safety of Swift
- [`Select<T>` clause](#selectt-clause)
- [`GroupBy` clause](#groupby-clause)
- [Logging and error handling](#logging-and-error-handling)
- [Observing changes and notifications](#observing-changes-and-notifications)
- [Observing changes and notifications](#observing-changes-and-notifications) (unavailable on OSX)
- [Observe a single object](#observe-a-single-object)
- [Observe a list of objects](#observe-a-list-of-objects)
- [Roadmap](#roadmap)
@@ -143,7 +146,7 @@ If you are already familiar with the inner workings of CoreData, here is a mappi
| --- | --- |
| `NSManagedObjectModel` / `NSPersistentStoreCoordinator`<br />(.xcdatamodeld file) | `DataStack` |
| `NSPersistentStore`<br />("Configuration"s in the .xcdatamodeld file) | `DataStack` configuration<br />(multiple sqlite / in-memory stores per stack) |
| `NSManagedObjectContext` | `BaseDataTransaction` subclasses<br />(`SynchronousDataTransaction`, `AsynchronousDataTransaction`, `DetachedDataTransaction`) |
| `NSManagedObjectContext` | `BaseDataTransaction` subclasses<br />(`SynchronousDataTransaction`, `AsynchronousDataTransaction`, `UnsafeDataTransaction`) |
Popular libraries [RestKit](https://github.com/RestKit/RestKit) and [MagicalRecord](https://github.com/magicalpanda/MagicalRecord) set up their `NSManagedObjectContext`s this way:
@@ -373,7 +376,7 @@ CoreStore.beginAsynchronous { (transaction) -> Void in
```
The `commit()` method saves the changes to the persistent store. If `commit()` is not called when the transaction block completes, all changes within the transaction is discarded.
The examples above use `beginAsynchronous(...)`, but there are actually 3 types of transactions at your disposal: *asynchronous*, *synchronous*, and *detached*.
The examples above use `beginAsynchronous(...)`, but there are actually 3 types of transactions at your disposal: *asynchronous*, *synchronous*, and *unsafe*.
### Transaction types
@@ -399,10 +402,10 @@ CoreStore.beginSynchronous { (transaction) -> Void in
Since `beginSynchronous(...)` technically blocks two queues (the caller's queue and the transaction's background queue), it is considered less safe as it's more prone to deadlock. Take special care that the closure does not block on any other external queues.
#### Detached transactions
#### Unsafe transactions
are special in that they do not enclose updates within a closure:
```swift
let transaction = CoreStore.beginDetached()
let transaction = CoreStore.beginUnsafe()
// make changes
downloadJSONWithCompletion({ (json) -> Void in
@@ -417,7 +420,7 @@ downloadAnotherJSONWithCompletion({ (json) -> Void in
```
This allows for non-contiguous updates. Do note that this flexibility comes with a price: you are now responsible for managing concurrency for the transaction. As uncle Ben said, "with great power comes great race conditions."
As the above example also shows, only detached transactions are allowed to call `commit()` multiple times; doing so with synchronous and asynchronous transactions will trigger an assert.
As the above example also shows, only unsafe transactions are allowed to call `commit()` multiple times; doing so with synchronous and asynchronous transactions will trigger an assert.
You've seen how to create transactions, but we have yet to see how to make *creates*, *updates*, and *deletes*. The 3 types of transactions above are all subclasses of `BaseDataTransaction`, which implements the methods shown below.
@@ -475,7 +478,7 @@ let jane: MyPersonEntity = // ...
CoreStore.beginAsynchronous { (transaction) -> Void in
// WRONG: jane.age = jane.age + 1
// RIGHT:
let jane = transaction.edit(jane) // using the same variable name protects us from misusing the non-transaction instance
let jane = transaction.edit(jane)! // using the same variable name protects us from misusing the non-transaction instance
jane.age = jane.age + 1
transaction.commit()
}
@@ -488,9 +491,9 @@ let john: MyPersonEntity = // ...
CoreStore.beginAsynchronous { (transaction) -> Void in
// WRONG: jane.friends = [john]
// RIGHT:
let jane = transaction.edit(jane)
let john = transaction.edit(john)
jane.friends = [john]
let jane = transaction.edit(jane)!
let john = transaction.edit(john)!
jane.friends = NSSet(array: [john])
transaction.commit()
}
```
@@ -528,6 +531,215 @@ CoreStore.beginAsynchronous { (transaction) -> Void in
}
```
### Passing objects safely
Always remember that the `DataStack` and individual transactions manage different `NSManagedObjectContext`s so you cannot just use objects between them. That's why transactions have an `edit(...)` method:
```swift
let jane: MyPersonEntity = // ...
CoreStore.beginAsynchronous { (transaction) -> Void in
let jane = transaction.edit(jane)!
jane.age = jane.age + 1
transaction.commit()
}
```
But `CoreStore`, `DataStack` and `BaseDataTransaction` have a very flexible `fetchExisting(...)` method that you can pass instances back and forth with:
```swift
let jane: MyPersonEntity = // ...
CoreStore.beginAsynchronous { (transaction) -> Void in
let jane = transaction.fetchExisting(jane)! // instance for transaction
jane.age = jane.age + 1
transaction.commit {
let jane = CoreStore.fetchExisting(jane)! // instance for DataStack
print(jane.age)
}
}
```
`fetchExisting(...)` also works with multiple `NSManagedObject`s or with `NSManagedObjectID`s:
```swift
var peopleIDs: [NSManagedObjectID] = // ...
CoreStore.beginAsynchronous { (transaction) -> Void in
let jane = transaction.fetchOne(
From(MyPersonEntity),
Where("name", isEqualTo: "Jane Smith")
)
jane.friends = NSSet(array: transactin.fetchExisting(peopleIDs)!)
// ...
}
```
## Importing data
Some times, if not most of the time, the data that we save to Core Data comes from external sources such as web servers or external files. Say you have a JSON dictionary, you may be extracting values as such:
```swift
let json: [String: AnyObject] = // ...
person.name = json["name"] as? NSString
person.age = json["age"] as? NSNumber
// ...
```
If you have many attributes, you don't want to keep repeating this mapping everytime you want to import data. CoreStore lets you write the data mapping code just once, and all you have to do is call `importObject(...)` or `importUniqueObject(...)` through `BaseDataTransaction` subclasses:
```swift
CoreStore.beginAsynchronous { (transaction) -> Void in
let json: [String: AnyObject] = // ...
try! transaction.importObject(
Into(MyPersonEntity),
source: json
)
transaction.commit()
}
```
To support data import for an entity, implement either `ImportableObject` or `ImportableUniqueObject` on the `NSManagedObject` subclass:
- `ImportableObject`: Use this protocol if the object have no inherent uniqueness and new objects should always be added when calling `importObject(...)`.
- `ImportableUniqueObject`: Use this protocol to specify a unique ID for an object that will be used to distinguish whether a new object should be created or if an existing object should be updated when calling `importUniqueObject(...)`.
Both protocols require implementers to specify an `ImportSource` which can be set to any type that the object can extract data from:
```swift
typealias ImportSource = NSDictionary
```
```swift
typealias ImportSource = [String: AnyObject]
```
```swift
typealias ImportSource = NSData
```
You can even use external types from popular 3rd-party JSON libraries ([SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON)'s `JSON` type is a personal favorite), or just simple tuples or primitives.
#### `ImportableObject`
`ImportableObject` is a very simple protocol:
```swift
public protocol ImportableObject: class {
typealias ImportSource
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
}
```
First, set `ImportSource` to the expected type of the data source:
```swift
typealias ImportSource = [String: AnyObject]
```
This lets us call `importObject(_:source:)` with any `[String: AnyObject]` type as the argument to `source`:
```swift
CoreStore.beginAsynchronous { (transaction) -> Void in
let json: [String: AnyObject] = // ...
try! transaction.importObject(
Into(MyPersonEntity),
source: json
)
// ...
}
```
The actual extraction and assignment of values should be implemented in the `didInsertFromImportSource(...)` method of the `ImportableObject` protocol:
```swift
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
self.name = source["name"] as? NSString
self.age = source["age"] as? NSNumber
// ...
}
```
Transactions also let you import multiple objects at once using the `importObjects(_:sourceArray:)` method:
```swift
CoreStore.beginAsynchronous { (transaction) -> Void in
let jsonArray: [[String: AnyObject]] = // ...
try! transaction.importObjects(
Into(MyPersonEntity),
sourceArray: jsonArray
)
// ...
}
```
Doing so tells the transaction to iterate through the array of import sources and calls `shouldInsertFromImportSource(...)` on the `ImportableObject` to determine which instances should be created. You can do validations and return `false` from `shouldInsertFromImportSource(...)` if you want to skip importing from a source and continue on with the other sources in the array.
If on the other hand, your validation in one of the sources failed in such a manner that all other sources should also be cancelled, you can `throw` from within `didInsertFromImportSource(...)`:
```swift
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
self.name = source["name"] as? NSString
self.age = source["age"] as? NSNumber
// ...
if self.name == nil {
throw Errors.InvalidNameError
}
}
```
Doing so can let you abandon an invalid transaction immediately:
```swift
CoreStore.beginAsynchronous { (transaction) -> Void in
let jsonArray: [[String: AnyObject]] = // ...
do {
try transaction.importObjects(
Into(MyPersonEntity),
sourceArray: jsonArray
)
}
catch {
return // Woops, don't save
}
transaction.commit {
// ...
}
}
```
#### `ImportableUniqueObject`
Typically, we don't just keep creating objects every time we import data. Usually we also need to update already existing objects. Implementing the `ImportableUniqueObject` protocol lets you specify a "unique ID" that transactions can use to search existing objects before creating new ones:
```swift
public protocol ImportableUniqueObject: ImportableObject {
typealias ImportSource
typealias UniqueIDType: NSObject
static var uniqueIDKeyPath: String { get }
var uniqueIDValue: UniqueIDType { get set }
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
static func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType?
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
}
```
Notice that it has the same insert methods as `ImportableObject`, with additional methods for updates and for specifying the unique ID:
```swift
class var uniqueIDKeyPath: String {
return "personID"
}
var uniqueIDValue: NSNumber {
get { return self.personID }
set { self.personID = newValue }
}
class func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> NSNumber? {
return source["id"] as? NSNumber
}
```
For `ImportableUniqueObject`, the extraction and assignment of values should be implemented from the `updateFromImportSource(...)` method. The `didInsertFromImportSource(...)` by default calls `updateFromImportSource(...)`, but you can separate the implementation for inserts and updates if needed.
You can then call create/update an object by calling a transaction's `importUniqueObject(...)` method:
```swift
CoreStore.beginAsynchronous { (transaction) -> Void in
let json: [String: AnyObject] = // ...
try! transaction.importUniqueObject(
Into(MyPersonEntity),
source: json
)
// ...
}
```
or multiple objects at once with the `importUniqueObjects(...)` method:
```swift
CoreStore.beginAsynchronous { (transaction) -> Void in
let jsonArray: [[String: AnyObject]] = // ...
try! transaction.importObjects(
Into(MyPersonEntity),
sourceArray: jsonArray
)
// ...
}
```
As with `ImportableObject`, you can control wether to skip importing an object by implementing
`shouldInsertFromImportSource(...)` and `shouldUpdateFromImportSource(...)`, or to cancel all objects by `throw`ing an error from the `uniqueIDFromImportSource(...)`, `didInsertFromImportSource(...)` or `updateFromImportSource(...)` methods.
## Fetching and Querying
Before we dive in, be aware that CoreStore distinguishes between *fetching* and *querying*:
- A *fetch* executes searches from a specific *transaction* or *data stack*. This means fetches can include pending objects (i.e. before a transaction calls on `commit()`.) Use fetches when:
@@ -812,7 +1024,7 @@ Doing so channels all logging calls to your logger.
Note that to keep the call stack information intact, all calls to these methods are **NOT** thread-managed. Therefore you have to make sure that your logger is thread-safe or you may otherwise have to dispatch your logging implementation to a serial queue.
## Observing changes and notifications
## Observing changes and notifications (unavailable on OSX)
CoreStore provides type-safe wrappers for observing managed objects:
- `ObjectMonitor`: use to monitor changes to a single `NSManagedObject` instance (instead of Key-Value Observing)
@@ -956,7 +1168,7 @@ let person2 = self.monitor[1, 2]
# Installation
- Requires:
- iOS 8 SDK and above
- Swift 2.0 (XCode 7 beta 5)
- Swift 2.0 (XCode 7 beta 6)
- Dependencies:
- [GCDKit](https://github.com/JohnEstropia/GCDKit)
@@ -968,7 +1180,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift
### Install with Carthage
```
github "JohnEstropia/CoreStore" >= 0.2.0
github "JohnEstropia/CoreStore" >= 1.3.0
```
### Install as Git Submodule