diff --git a/.gitmodules b/.gitmodules index 5fec53f..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "Carthage/Checkouts/GCDKit"] - path = Carthage/Checkouts/GCDKit - url = https://github.com/JohnEstropia/GCDKit.git diff --git a/.travis.yml b/.travis.yml index 9f72063..b3c0935 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode8 +osx_image: xcode8.2 sudo: false git: submodules: false @@ -10,17 +10,17 @@ env: - LC_CTYPE=en_US.UTF-8 - LANG=en_US.UTF-8 matrix: - - DESTINATION="OS=10.0,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="YES" RUN_DEMO="YES" - - DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO" RUN_DEMO="YES" -# iOS 8 testing currently broken on Xcode 8 -# - DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO" RUN_DEMO="YES" -# - DESTINATION="OS=8.3,name=iPhone 5s" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO" RUN_DEMO="YES" -# - DESTINATION="OS=8.2,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO" RUN_DEMO="YES" -# - DESTINATION="OS=8.1,name=iPhone 4s" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO" RUN_DEMO="YES" - - DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 RUN_TESTS="YES" POD_LINT="NO" RUN_DEMO="NO" - - DESTINATION="OS=3.0,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.0 RUN_TESTS="NO" POD_LINT="NO" RUN_DEMO="NO" - - DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.0 RUN_TESTS="NO" POD_LINT="NO" RUN_DEMO="NO" - - DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.0 RUN_TESTS="YES" POD_LINT="NO" RUN_DEMO="NO" + - DESTINATION="OS=10.1,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=8.3,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=8.3,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.2 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=3.1,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.1 RUN_TESTS="NO" POD_LINT="NO" + - DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.1 RUN_TESTS="NO" POD_LINT="NO" + - DESTINATION="OS=10.1,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.1 RUN_TESTS="YES" POD_LINT="NO" + - DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.1 RUN_TESTS="YES" POD_LINT="NO" before_install: - gem install cocoapods --no-rdoc --no-ri --no-document --quiet - gem install xcpretty --no-rdoc --no-ri --no-document --quiet @@ -37,9 +37,8 @@ script: xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; fi - - if [ $RUN_DEMO == "YES" ]; then - xcodebuild -workspace CoreStore.xcworkspace -scheme "CoreStoreDemo" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean build | xcpretty -c; - fi + - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.2" -destination "OS=10.1,name=iPhone 7" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; + - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.2" -destination "OS=10.1,name=iPhone 7" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; - if [ $POD_LINT == "YES" ]; then pod lib lint --quick; fi diff --git a/Cartfile b/Cartfile index bcc5dc5..e69de29 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +0,0 @@ -github "JohnEstropia/GCDKit" == 1.3.0 diff --git a/Cartfile.resolved b/Cartfile.resolved index 15eb782..e69de29 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +0,0 @@ -github "JohnEstropia/GCDKit" "1.3.0" diff --git a/Carthage/Checkouts/GCDKit b/Carthage/Checkouts/GCDKit deleted file mode 160000 index a7f2b8a..0000000 --- a/Carthage/Checkouts/GCDKit +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a7f2b8ac848eaa3ec97682f165505fa377f1fe8c diff --git a/CoreStore.podspec b/CoreStore.podspec index c6dfd25..a83f5e6 100644 --- a/CoreStore.podspec +++ b/CoreStore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "CoreStore" - s.version = "2.1.3" + s.version = "3.0.0" s.license = "MIT" s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift" s.homepage = "https://github.com/JohnEstropia/CoreStore" @@ -19,6 +19,4 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D USE_FRAMEWORKS -D DEBUG', 'OTHER_SWIFT_FLAGS[config=Release]' => '-D USE_FRAMEWORKS', 'GCC_PREPROCESSOR_DEFINITIONS' => 'USE_FRAMEWORKS=1' } - - s.dependency "GCDKit", "1.3.0" end diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index 945fea2..4565140 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -54,7 +54,7 @@ 82BA18C91C4BBD5900A0916E /* MigrationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A261201B64BFDB006EB6D3 /* MigrationType.swift */; }; 82BA18CA1C4BBD5900A0916E /* MigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965231B356B820075EE4A /* MigrationResult.swift */; }; 82BA18CB1C4BBD6400A0916E /* NSManagedObject+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F271AFF84920064E85B /* NSManagedObject+Convenience.swift */; }; - 82BA18CC1C4BBD6400A0916E /* NSProgress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */; }; + 82BA18CC1C4BBD6400A0916E /* Progress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* Progress+Convenience.swift */; }; 82BA18CE1C4BBD7100A0916E /* FetchedResultsControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */; }; 82BA18CF1C4BBD7100A0916E /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834BA1B7691F3001D3D50 /* Functions.swift */; }; 82BA18D01C4BBD7100A0916E /* MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6AB1B51285300714891 /* MigrationManager.swift */; }; @@ -67,8 +67,6 @@ 82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; }; 82BA18DC1C4BBD9C00A0916E /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; }; 82BA18DD1C4BBE1400A0916E /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; }; - 82BA18DF1C4BBE2600A0916E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82BA18DE1C4BBE2600A0916E /* Foundation.framework */; }; - 82BA18E11C4BBE2C00A0916E /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82BA18E01C4BBE2C00A0916E /* CoreData.framework */; }; B501FDDD1CA8D05000BE22EF /* CSSectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501FDDC1CA8D05000BE22EF /* CSSectionBy.swift */; }; B501FDDF1CA8D05000BE22EF /* CSSectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501FDDC1CA8D05000BE22EF /* CSSectionBy.swift */; }; B501FDE01CA8D05000BE22EF /* CSSectionBy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B501FDDC1CA8D05000BE22EF /* CSSectionBy.swift */; }; @@ -82,10 +80,6 @@ B50392FA1C47963F009900CA /* NSManagedObject+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50392F81C478FF3009900CA /* NSManagedObject+Transaction.swift */; }; B50392FB1C479640009900CA /* NSManagedObject+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50392F81C478FF3009900CA /* NSManagedObject+Transaction.swift */; }; B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */; }; - B519E4581C4CD2CA00E7B469 /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B519E4571C4CD2CA00E7B469 /* GCDKit.framework */; }; - B519E4591C4CD2D100E7B469 /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B519E4571C4CD2CA00E7B469 /* GCDKit.framework */; }; - B519E45A1C4CD2DA00E7B469 /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B519E4571C4CD2CA00E7B469 /* GCDKit.framework */; }; - B519E45B1C4CD2ED00E7B469 /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B519E4571C4CD2CA00E7B469 /* GCDKit.framework */; }; B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; }; B51FE5AB1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; }; B51FE5AD1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; }; @@ -145,13 +139,15 @@ B52557881D02DE8100E51965 /* FetchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52557871D02DE8100E51965 /* FetchTests.swift */; }; B52557891D02DE8100E51965 /* FetchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52557871D02DE8100E51965 /* FetchTests.swift */; }; B525578A1D02DE8100E51965 /* FetchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52557871D02DE8100E51965 /* FetchTests.swift */; }; + B52661401CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */; }; + B52661421CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */; }; + B52661431CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */; }; + B52661441CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */; }; B529C2041CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */; }; B529C2061CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */; }; B529C2071CA4A2DC007E7EBD /* CSSaveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */; }; B529C2081CA4A2DC007E7EBD /* CSSaveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */; }; B52DD17E1BE1F8CD00949AFE /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52DD1741BE1F8CC00949AFE /* CoreStore.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 /* CoreStoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */; }; @@ -187,7 +183,7 @@ 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 */; }; + B52DD1BE1BE1F94300949AFE /* Progress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* Progress+Convenience.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 */; }; @@ -197,6 +193,10 @@ 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 */; }; + B533C4DB1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; }; + B533C4DC1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; }; + B533C4DD1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; }; + B533C4DE1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; }; B538BA771D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; }; B538BA781D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; }; B538BA791D15B3E30003A766 /* CoreStoreBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = B538BA701D15B3E30003A766 /* CoreStoreBridge.m */; }; @@ -213,10 +213,10 @@ B53FBA0D1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA0A1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift */; }; B53FBA0E1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA0A1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift */; }; B53FBA0F1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA0A1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift */; }; - B53FBA121CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA111CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift */; }; - B53FBA141CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA111CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift */; }; - B53FBA151CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA111CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift */; }; - B53FBA161CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA111CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift */; }; + B53FBA121CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA111CAB63CB00F0D40A /* Progress+ObjectiveC.swift */; }; + B53FBA141CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA111CAB63CB00F0D40A /* Progress+ObjectiveC.swift */; }; + B53FBA151CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA111CAB63CB00F0D40A /* Progress+ObjectiveC.swift */; }; + B53FBA161CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA111CAB63CB00F0D40A /* Progress+ObjectiveC.swift */; }; B53FBA181CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA171CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift */; }; B53FBA1A1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA171CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift */; }; B53FBA1B1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FBA171CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift */; }; @@ -287,8 +287,6 @@ 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 */; }; 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 /* CoreStoreError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */; }; @@ -331,7 +329,7 @@ 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 */; }; + B56321A91BD65219006C9394 /* Progress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* Progress+Convenience.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 */; }; @@ -342,6 +340,12 @@ 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 */; }; + B56507941D3930BC000596DA /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56507931D3930BC000596DA /* CoreData.framework */; }; + B56507961D3930C1000596DA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56507951D3930C1000596DA /* Foundation.framework */; }; + B56507981D3930CC000596DA /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56507971D3930CC000596DA /* CoreData.framework */; }; + B565079A1D3930D1000596DA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B56507991D3930D1000596DA /* Foundation.framework */; }; + B565079E1D3930ED000596DA /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B565079D1D3930ED000596DA /* CoreData.framework */; }; + B56507A01D3930F5000596DA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B565079F1D3930F5000596DA /* Foundation.framework */; }; B5677D3D1CD3B1E400322BFC /* ICloudStoreObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5677D3C1CD3B1E400322BFC /* ICloudStoreObserver.swift */; }; B5677D3F1CD3B1E400322BFC /* ICloudStoreObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5677D3C1CD3B1E400322BFC /* ICloudStoreObserver.swift */; }; B5677D401CD3B1E400322BFC /* ICloudStoreObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5677D3C1CD3B1E400322BFC /* ICloudStoreObserver.swift */; }; @@ -358,6 +362,17 @@ B580857B1CDF808D004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; }; B580857C1CDF808F004C2EEB /* SetupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58085741CDF7F00004C2EEB /* SetupTests.swift */; }; B58B22F51C93C1BA00521925 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A53019C5C6DA005002A5 /* CoreStore.framework */; }; + B596BBB21DD5A014001DCDD9 /* ConvenienceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBAD1DD59FDB001DCDD9 /* ConvenienceTests.swift */; }; + B596BBB31DD5A014001DCDD9 /* ConvenienceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBAD1DD59FDB001DCDD9 /* ConvenienceTests.swift */; }; + B596BBB41DD5A016001DCDD9 /* ConvenienceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBAD1DD59FDB001DCDD9 /* ConvenienceTests.swift */; }; + B596BBB61DD5BC67001DCDD9 /* FetchableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */; }; + B596BBB71DD5BC67001DCDD9 /* FetchableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */; }; + B596BBB81DD5BC67001DCDD9 /* FetchableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */; }; + B596BBB91DD5BC67001DCDD9 /* FetchableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */; }; + B596BBBB1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBBA1DD5C39F001DCDD9 /* QueryableSource.swift */; }; + B596BBBC1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBBA1DD5C39F001DCDD9 /* QueryableSource.swift */; }; + B596BBBD1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBBA1DD5C39F001DCDD9 /* QueryableSource.swift */; }; + B596BBBE1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B596BBBA1DD5C39F001DCDD9 /* QueryableSource.swift */; }; B59851491C90289D00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59AFF401C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift */; }; B598514A1C90289E00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59AFF401C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift */; }; B598514B1C90289F00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59AFF401C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift */; }; @@ -519,7 +534,7 @@ B5ECDC331CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5ECDC2E1CA81CDC00C7F112 /* CSCoreStore+Transaction.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 */; }; + B5FAD6A91B50A4B400714891 /* Progress+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FAD6A81B50A4B300714891 /* Progress+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 */; }; B5FE4DA21C8481E100FA6A91 /* StorageInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FE4DA11C8481E100FA6A91 /* StorageInterface.swift */; }; @@ -581,7 +596,6 @@ B501FDE61CA8D20500BE22EF /* CSListObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSListObserver.swift; sourceTree = ""; }; B50392F81C478FF3009900CA /* NSManagedObject+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Transaction.swift"; sourceTree = ""; }; B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Setup.swift"; sourceTree = ""; }; - B519E4571C4CD2CA00E7B469 /* GCDKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GCDKit.framework; path = "../../Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphoneos/GCDKit.framework"; sourceTree = ""; }; B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectModel+Setup.swift"; sourceTree = ""; }; B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+CustomDebugStringConvertible.swift"; sourceTree = ""; }; B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFetchedResultsController+Convenience.swift"; sourceTree = ""; }; @@ -596,14 +610,16 @@ B525577F1D029D2500E51965 /* TweakTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TweakTests.swift; sourceTree = ""; }; B52557831D02A07400E51965 /* SectionByTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionByTests.swift; sourceTree = ""; }; B52557871D02DE8100E51965 /* FetchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchTests.swift; sourceTree = ""; }; + B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStoreFetchRequest+CoreStore.swift"; sourceTree = ""; }; B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSaveResult.swift; sourceTree = ""; }; 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; }; + B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+CoreStore.swift"; sourceTree = ""; }; B538BA701D15B3E30003A766 /* CoreStoreBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreStoreBridge.m; sourceTree = ""; }; B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSMigrationResult.swift; sourceTree = ""; }; B53FBA031CAB300C00F0D40A /* CSMigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSMigrationType.swift; sourceTree = ""; }; B53FBA0A1CAB5E6500F0D40A /* CSCoreStore+Migrating.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Migrating.swift"; sourceTree = ""; }; - B53FBA111CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSProgress+ObjectiveC.swift"; sourceTree = ""; }; + B53FBA111CAB63CB00F0D40A /* Progress+ObjectiveC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Progress+ObjectiveC.swift"; sourceTree = ""; }; B53FBA171CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+ObjectiveC.swift"; sourceTree = ""; }; B53FBA1D1CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFetchedResultsController+ObjectiveC.swift"; sourceTree = ""; }; B546F9571C99B17400D5AC55 /* CSCoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Setup.swift"; sourceTree = ""; }; @@ -631,12 +647,21 @@ 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; }; + B56507931D3930BC000596DA /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS10.0.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; }; + B56507951D3930C1000596DA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + B56507971D3930CC000596DA /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; }; + B56507991D3930D1000596DA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + B565079D1D3930ED000596DA /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; }; + B565079F1D3930F5000596DA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; B5677D3C1CD3B1E400322BFC /* ICloudStoreObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICloudStoreObserver.swift; sourceTree = ""; }; - B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DataStack+Migration.swift"; sourceTree = ""; }; + B56964D31B22FFAD0075EE4A /* DataStack+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "DataStack+Migration.swift"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; B56965231B356B820075EE4A /* MigrationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationResult.swift; sourceTree = ""; }; B57D27BD1D0BBE8200539C58 /* BaseTestDataTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTestDataTestCase.swift; sourceTree = ""; }; B57D27C11D0BC20100539C58 /* QueryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryTests.swift; sourceTree = ""; }; B58085741CDF7F00004C2EEB /* SetupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetupTests.swift; sourceTree = ""; }; + B596BBAD1DD59FDB001DCDD9 /* ConvenienceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConvenienceTests.swift; sourceTree = ""; }; + B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchableSource.swift; sourceTree = ""; }; + B596BBBA1DD5C39F001DCDD9 /* QueryableSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryableSource.swift; sourceTree = ""; }; B59AFF401C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSPersistentStoreCoordinator+Setup.swift"; sourceTree = ""; }; B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICloudStore.swift; sourceTree = ""; }; B5A261201B64BFDB006EB6D3 /* MigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationType.swift; sourceTree = ""; }; @@ -719,9 +744,9 @@ B5ECDC2E1CA81CDC00C7F112 /* CSCoreStore+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Transaction.swift"; sourceTree = ""; }; B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableObject.swift; sourceTree = ""; }; B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportableUniqueObject.swift; sourceTree = ""; }; - B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSProgress+Convenience.swift"; sourceTree = ""; }; + B5FAD6A81B50A4B300714891 /* Progress+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Progress+Convenience.swift"; sourceTree = ""; }; B5FAD6AB1B51285300714891 /* MigrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationManager.swift; sourceTree = ""; }; - B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+Migration.swift"; sourceTree = ""; }; + B5FAD6AD1B518DCB00714891 /* CoreStore+Migration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "CoreStore+Migration.swift"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; B5FE4DA11C8481E100FA6A91 /* StorageInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageInterface.swift; sourceTree = ""; }; B5FE4DA61C84FB4400FA6A91 /* InMemoryStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InMemoryStore.swift; sourceTree = ""; }; B5FE4DAB1C85D44E00FA6A91 /* SQLiteStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteStore.swift; sourceTree = ""; }; @@ -733,7 +758,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B519E4581C4CD2CA00E7B469 /* GCDKit.framework in Frameworks */, B5D39A0219FD00C9000E91BB /* Foundation.framework in Frameworks */, 2F03A54D19C5C872005002A5 /* CoreData.framework in Frameworks */, ); @@ -751,9 +775,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B519E4591C4CD2D100E7B469 /* GCDKit.framework in Frameworks */, - 82BA18E11C4BBE2C00A0916E /* CoreData.framework in Frameworks */, - 82BA18DF1C4BBE2600A0916E /* Foundation.framework in Frameworks */, + B56507961D3930C1000596DA /* Foundation.framework in Frameworks */, + B56507941D3930BC000596DA /* CoreData.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -769,9 +792,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B519E45A1C4CD2DA00E7B469 /* GCDKit.framework in Frameworks */, - B52DD1921BE1F8F000949AFE /* CoreData.framework in Frameworks */, - B52DD1911BE1F8EB00949AFE /* Foundation.framework in Frameworks */, + B56507A01D3930F5000596DA /* Foundation.framework in Frameworks */, + B565079E1D3930ED000596DA /* CoreData.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -787,9 +809,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B519E45B1C4CD2ED00E7B469 /* GCDKit.framework in Frameworks */, - B563217C1BD650E3006C9394 /* Foundation.framework in Frameworks */, - B563217A1BD650DE006C9394 /* CoreData.framework in Frameworks */, + B565079A1D3930D1000596DA /* Foundation.framework in Frameworks */, + B56507981D3930CC000596DA /* CoreData.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -865,6 +886,7 @@ B52557831D02A07400E51965 /* SectionByTests.swift */, B525576F1D02561A00E51965 /* SelectTests.swift */, B58085741CDF7F00004C2EEB /* SetupTests.swift */, + B596BBAD1DD59FDB001DCDD9 /* ConvenienceTests.swift */, B5DC47C91C93D9C800FA3BF3 /* StorageInterfaceTests.swift */, 2F03A53D19C5C6DA005002A5 /* Supporting Files */, B5489F3C1CF5EEBC008B4978 /* TestEntities */, @@ -888,7 +910,12 @@ 2F291E3119C6D4D3007AF63F /* Frameworks */ = { isa = PBXGroup; children = ( - B519E4571C4CD2CA00E7B469 /* GCDKit.framework */, + B565079F1D3930F5000596DA /* Foundation.framework */, + B565079D1D3930ED000596DA /* CoreData.framework */, + B56507991D3930D1000596DA /* Foundation.framework */, + B56507971D3930CC000596DA /* CoreData.framework */, + B56507951D3930C1000596DA /* Foundation.framework */, + B56507931D3930BC000596DA /* CoreData.framework */, B5548CD71BD65AE50077652A /* CoreData.framework */, B56321791BD650DE006C9394 /* CoreData.framework */, 82BA18E01C4BBE2C00A0916E /* CoreData.framework */, @@ -919,7 +946,7 @@ isa = PBXGroup; children = ( B53FBA171CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift */, - B53FBA111CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift */, + B53FBA111CAB63CB00F0D40A /* Progress+ObjectiveC.swift */, B53FBA1D1CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift */, ); name = Convenience; @@ -1113,6 +1140,8 @@ B5E84EFE1AFF847B0064E85B /* BaseDataTransaction+Querying.swift */, B5E84F061AFF847B0064E85B /* DataStack+Querying.swift */, B5E84F071AFF847B0064E85B /* CoreStore+Querying.swift */, + B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */, + B596BBBA1DD5C39F001DCDD9 /* QueryableSource.swift */, B5E84F0A1AFF847B0064E85B /* Protocol Clauses */, B5E84EFF1AFF847B0064E85B /* Concrete Clauses */, ); @@ -1159,7 +1188,7 @@ isa = PBXGroup; children = ( B5E84F271AFF84920064E85B /* NSManagedObject+Convenience.swift */, - B5FAD6A81B50A4B300714891 /* NSProgress+Convenience.swift */, + B5FAD6A81B50A4B300714891 /* Progress+Convenience.swift */, B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */, ); path = Convenience; @@ -1169,10 +1198,12 @@ isa = PBXGroup; children = ( B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */, + B526613F1CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift */, B54A6A541BA15F2A007870FD /* FetchedResultsControllerDelegate.swift */, B5E834BA1B7691F3001D3D50 /* Functions.swift */, B5FAD6AB1B51285300714891 /* MigrationManager.swift */, B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */, + B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */, B5E84F2C1AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift */, B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */, B5E84F321AFF85470064E85B /* NSManagedObjectContext+Setup.swift */, @@ -1423,7 +1454,6 @@ }; B563216E1BD65082006C9394 = { CreatedOnToolsVersion = 7.0.1; - LastSwiftMigration = 0800; }; }; }; @@ -1517,6 +1547,7 @@ B5D1E22C19FA9FBC003B2874 /* CoreStoreError.swift in Sources */, B5E84F131AFF847B0064E85B /* Where.swift in Sources */, B5D3F6451C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */, + B596BBBB1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */, B5ECDBFF1CA80CBA00C7F112 /* CSWhere.swift in Sources */, B5ECDC051CA8138100C7F112 /* CSOrderBy.swift in Sources */, B5E1B5981CAA0C23007FD580 /* CSObjectObserver.swift in Sources */, @@ -1531,7 +1562,7 @@ B5E84F371AFF85470064E85B /* NSManagedObjectContext+Transaction.swift in Sources */, B5ECDC1D1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, B5C976E31C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, - B53FBA121CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift in Sources */, + B53FBA121CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, B5E1B5A81CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */, B56007161B4018AB00A9A8F9 /* MigrationChain.swift in Sources */, B5E1B59D1CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */, @@ -1552,6 +1583,7 @@ B53FB9FE1CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */, B5DBE2D21C991B3E00B5CEFA /* CSDataStack.swift in Sources */, B50392F91C478FF3009900CA /* NSManagedObject+Transaction.swift in Sources */, + B52661401CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift in Sources */, B53FBA181CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */, B5202CFA1C04688100DED140 /* NSFetchedResultsController+Convenience.swift in Sources */, B5519A591CA2008C002BEF78 /* CSBaseDataTransaction.swift in Sources */, @@ -1570,6 +1602,7 @@ B5FAD6AC1B51285300714891 /* MigrationManager.swift in Sources */, B5E84EF61AFF846E0064E85B /* DataStack+Transaction.swift in Sources */, B5FEC18E1C9166E200532541 /* NSPersistentStore+Setup.swift in Sources */, + B596BBB61DD5BC67001DCDD9 /* FetchableSource.swift in Sources */, B5E1B5A21CAA4365007FD580 /* CSCoreStore+Observing.swift in Sources */, B5E84EDF1AFF84500064E85B /* DataStack.swift in Sources */, B59AFF411C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift in Sources */, @@ -1583,7 +1616,7 @@ B5E84EF51AFF846E0064E85B /* BaseDataTransaction.swift in Sources */, B5E84EFB1AFF846E0064E85B /* SaveResult.swift in Sources */, B5E84F0F1AFF847B0064E85B /* From.swift in Sources */, - B5FAD6A91B50A4B400714891 /* NSProgress+Convenience.swift in Sources */, + B5FAD6A91B50A4B400714891 /* Progress+Convenience.swift in Sources */, B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */, B5E222231CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, B5E84F281AFF84920064E85B /* NSManagedObject+Convenience.swift in Sources */, @@ -1592,6 +1625,7 @@ B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */, B5E84EE81AFF84610064E85B /* CoreStoreLogger.swift in Sources */, + B533C4DB1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */, B559CD491CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */, B5ECDC2F1CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */, B5E84F311AFF849C0064E85B /* WeakObject.swift in Sources */, @@ -1625,6 +1659,7 @@ buildActionMask = 2147483647; files = ( B52557841D02A07400E51965 /* SectionByTests.swift in Sources */, + B596BBB21DD5A014001DCDD9 /* ConvenienceTests.swift in Sources */, B5220E101D0DA6AB009BC71E /* ListObserverTests.swift in Sources */, B5519A401CA1B17B002BEF78 /* ErrorTests.swift in Sources */, B525577C1D0291FE00E51965 /* GroupByTests.swift in Sources */, @@ -1664,6 +1699,7 @@ 82BA18AE1C4BBD3100A0916E /* DataStack+Transaction.swift in Sources */, 82BA18AB1C4BBD3100A0916E /* AsynchronousDataTransaction.swift in Sources */, 82BA18CE1C4BBD7100A0916E /* FetchedResultsControllerDelegate.swift in Sources */, + B596BBBC1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */, B5ECDC011CA80CBA00C7F112 /* CSWhere.swift in Sources */, B5ECDC071CA8138100C7F112 /* CSOrderBy.swift in Sources */, B5E1B59A1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */, @@ -1678,7 +1714,7 @@ 82BA18BD1C4BBD4A00A0916E /* GroupBy.swift in Sources */, B5ECDC1F1CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, B5C976E41C6C9F9A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, - B53FBA141CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift in Sources */, + B53FBA141CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, B5E1B5AA1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */, B5D3F6461C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */, B5E1B59F1CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */, @@ -1701,6 +1737,7 @@ 82BA18B41C4BBD3900A0916E /* BaseDataTransaction+Importing.swift in Sources */, B53FBA1A1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */, 82BA18CA1C4BBD5900A0916E /* MigrationResult.swift in Sources */, + B52661421CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift in Sources */, B5519A5A1CA2008C002BEF78 /* CSBaseDataTransaction.swift in Sources */, B5ECDBE11CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift in Sources */, 82BA18C11C4BBD5300A0916E /* CoreStore+Observing.swift in Sources */, @@ -1717,6 +1754,7 @@ 82BA18C61C4BBD5900A0916E /* DataStack+Migration.swift in Sources */, B59851491C90289D00C99590 /* NSPersistentStoreCoordinator+Setup.swift in Sources */, B5E1B5A41CAA4365007FD580 /* CSCoreStore+Observing.swift in Sources */, + B596BBB71DD5BC67001DCDD9 /* FetchableSource.swift in Sources */, B5FEC18F1C9166E600532541 /* NSPersistentStore+Setup.swift in Sources */, 82BA18B71C4BBD3F00A0916E /* CoreStore+Querying.swift in Sources */, 82BA18AA1C4BBD3100A0916E /* BaseDataTransaction.swift in Sources */, @@ -1739,6 +1777,7 @@ 82BA18A71C4BBD2900A0916E /* CoreStore+Logging.swift in Sources */, 82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */, B559CD4B1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */, + B533C4DC1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */, B5ECDC311CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */, 82BA18AF1C4BBD3100A0916E /* CoreStore+Transaction.swift in Sources */, 82BA18CB1C4BBD6400A0916E /* NSManagedObject+Convenience.swift in Sources */, @@ -1761,7 +1800,7 @@ B5DBE2CE1C9914A900B5CEFA /* CSCoreStore.swift in Sources */, B546F95E1C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */, B5ECDC0D1CA8161B00C7F112 /* CSGroupBy.swift in Sources */, - 82BA18CC1C4BBD6400A0916E /* NSProgress+Convenience.swift in Sources */, + 82BA18CC1C4BBD6400A0916E /* Progress+Convenience.swift in Sources */, 82BA18C01C4BBD5300A0916E /* DataStack+Observing.swift in Sources */, 82BA18A61C4BBD2900A0916E /* DefaultLogger.swift in Sources */, ); @@ -1772,6 +1811,7 @@ buildActionMask = 2147483647; files = ( B52557851D02A07400E51965 /* SectionByTests.swift in Sources */, + B596BBB31DD5A014001DCDD9 /* ConvenienceTests.swift in Sources */, B5220E111D0DA6AB009BC71E /* ListObserverTests.swift in Sources */, B5519A411CA1B17B002BEF78 /* ErrorTests.swift in Sources */, B525577D1D0291FE00E51965 /* GroupByTests.swift in Sources */, @@ -1805,12 +1845,13 @@ B5220E1E1D13080D009BC71E /* CSListMonitor.swift in Sources */, B5DBE2D01C9914A900B5CEFA /* CSCoreStore.swift in Sources */, B5677D411CD3B1E400322BFC /* ICloudStoreObserver.swift in Sources */, - B52DD1BE1BE1F94300949AFE /* NSProgress+Convenience.swift in Sources */, + B52DD1BE1BE1F94300949AFE /* Progress+Convenience.swift in Sources */, B5ECDC151CA816E500C7F112 /* CSTweak.swift in Sources */, B546F9761C9C553300D5AC55 /* SetupResult.swift in Sources */, - B53FBA161CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift in Sources */, + B53FBA161CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, B5ECDC271CA81A3900C7F112 /* CSCoreStore+Querying.swift in Sources */, B52DD1951BE1F92500949AFE /* CoreStoreError.swift in Sources */, + B596BBBE1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */, B546F9601C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */, B5ECDC0F1CA8161B00C7F112 /* CSGroupBy.swift in Sources */, B5ECDC211CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, @@ -1849,6 +1890,7 @@ B52DD1C71BE1F94600949AFE /* NSManagedObjectContext+Querying.swift in Sources */, B52DD1C81BE1F94600949AFE /* NSManagedObjectContext+Setup.swift in Sources */, B52DD1C31BE1F94600949AFE /* NotificationObserver.swift in Sources */, + B52661441CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift in Sources */, B52DD1A81BE1F93200949AFE /* DataStack+Querying.swift in Sources */, B5220E221D130818009BC71E /* CSSectionBy.swift in Sources */, B52DD1BC1BE1F94000949AFE /* MigrationResult.swift in Sources */, @@ -1864,6 +1906,7 @@ B5519A621CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B52DD19C1BE1F92C00949AFE /* Into.swift in Sources */, B5FE4DA51C8481E100FA6A91 /* StorageInterface.swift in Sources */, + B596BBB91DD5BC67001DCDD9 /* FetchableSource.swift in Sources */, B529C2081CA4A2DC007E7EBD /* CSSaveResult.swift in Sources */, B5FE4DAA1C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B52DD1AF1BE1F93900949AFE /* GroupBy.swift in Sources */, @@ -1886,6 +1929,7 @@ B52DD1A71BE1F93200949AFE /* BaseDataTransaction+Querying.swift in Sources */, B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B52DD1C61BE1F94600949AFE /* NSManagedObjectContext+CoreStore.swift in Sources */, + B533C4DE1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */, B5220E141D130614009BC71E /* DataStack+Observing.swift in Sources */, B52DD1A21BE1F92C00949AFE /* CoreStore+Transaction.swift in Sources */, B5E2222E1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, @@ -1919,6 +1963,7 @@ buildActionMask = 2147483647; files = ( B5519A421CA1B17B002BEF78 /* ErrorTests.swift in Sources */, + B596BBB41DD5A016001DCDD9 /* ConvenienceTests.swift in Sources */, B5220E271D1308D1009BC71E /* ObjectObserverTests.swift in Sources */, B525577E1D0291FE00E51965 /* GroupByTests.swift in Sources */, B52557761D02791400E51965 /* WhereTests.swift in Sources */, @@ -1949,7 +1994,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B56321A91BD65219006C9394 /* NSProgress+Convenience.swift in Sources */, + B56321A91BD65219006C9394 /* Progress+Convenience.swift in Sources */, B5ECDBFC1CA804FD00C7F112 /* NSManagedObjectContext+ObjectiveC.swift in Sources */, B5C976E91C6E3A5E00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */, B56321801BD65216006C9394 /* CoreStoreError.swift in Sources */, @@ -1958,6 +2003,7 @@ B563219D1BD65216006C9394 /* DataStack+Observing.swift in Sources */, B56321961BD65216006C9394 /* From.swift in Sources */, B5ECDC021CA80CBA00C7F112 /* CSWhere.swift in Sources */, + B596BBBD1DD5C39F001DCDD9 /* QueryableSource.swift in Sources */, B5ECDC081CA8138100C7F112 /* CSOrderBy.swift in Sources */, B5E1B59B1CAA0C23007FD580 /* CSObjectObserver.swift in Sources */, B5519A611CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, @@ -1971,7 +2017,7 @@ B56321831BD65216006C9394 /* CoreStore+Setup.swift in Sources */, B5ECDC201CA81A2100C7F112 /* CSDataStack+Querying.swift in Sources */, B5C976E51C6C9F9B00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, - B53FBA151CAB63CB00F0D40A /* NSProgress+ObjectiveC.swift in Sources */, + B53FBA151CAB63CB00F0D40A /* Progress+ObjectiveC.swift in Sources */, B5E1B5AB1CAA49E2007FD580 /* CSDataStack+Migrating.swift in Sources */, B5D3F6471C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */, B5E1B5A01CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */, @@ -1992,6 +2038,7 @@ B53FBA011CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */, B5DBE2D41C991B3E00B5CEFA /* CSDataStack.swift in Sources */, B50392FA1C47963F009900CA /* NSManagedObject+Transaction.swift in Sources */, + B52661431CADD585007B85D9 /* CoreStoreFetchRequest+CoreStore.swift in Sources */, B53FBA1B1CAB63E200F0D40A /* NSManagedObject+ObjectiveC.swift in Sources */, B5519A5B1CA2008C002BEF78 /* CSBaseDataTransaction.swift in Sources */, B5ECDBE21CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift in Sources */, @@ -2011,6 +2058,7 @@ B5FEC1901C9166E700532541 /* NSPersistentStore+Setup.swift in Sources */, B56321A11BD65216006C9394 /* ListMonitor.swift in Sources */, B5E1B5A51CAA4365007FD580 /* CSCoreStore+Observing.swift in Sources */, + B596BBB81DD5BC67001DCDD9 /* FetchableSource.swift in Sources */, B56321881BD65216006C9394 /* BaseDataTransaction.swift in Sources */, B56321A31BD65216006C9394 /* DataStack+Migration.swift in Sources */, B56321901BD65216006C9394 /* ImportableUniqueObject.swift in Sources */, @@ -2033,6 +2081,7 @@ B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */, B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */, B559CD4C1CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */, + B533C4DD1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */, B5ECDC321CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */, B56321AC1BD6521C006C9394 /* Functions.swift in Sources */, B56321851BD65216006C9394 /* CoreStore+Logging.swift in Sources */, @@ -2208,7 +2257,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -2226,13 +2275,14 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Release; }; 2F03A54719C5C6DA005002A5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; CLANG_ENABLE_MODULES = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -2245,13 +2295,14 @@ SDKROOT = iphoneos; SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; 2F03A54819C5C6DA005002A5 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; CLANG_ENABLE_MODULES = YES; INFOPLIST_FILE = CoreStoreTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -2259,7 +2310,7 @@ PRODUCT_NAME = CoreStoreTests; SDKROOT = iphoneos; SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -2272,13 +2323,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = 3; }; name = Debug; @@ -2292,13 +2344,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = 3; }; name = Release; @@ -2306,6 +2359,7 @@ 82BA189C1C4BBCBA00A0916E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; CLANG_ENABLE_MODULES = YES; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = CoreStoreTests/Info.plist; @@ -2315,7 +2369,7 @@ SDKROOT = appletvos; SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = 3; }; name = Debug; @@ -2323,6 +2377,7 @@ 82BA189D1C4BBCBA00A0916E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; CLANG_ENABLE_MODULES = YES; COPY_PHASE_STRIP = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -2332,7 +2387,7 @@ PRODUCT_NAME = CoreStoreTests; SDKROOT = appletvos; SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = 3; }; name = Release; @@ -2348,6 +2403,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -2355,7 +2411,7 @@ SDKROOT = macosx; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -2371,6 +2427,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -2378,13 +2435,14 @@ SDKROOT = macosx; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Release; }; B52DD1871BE1F8CD00949AFE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; @@ -2397,13 +2455,14 @@ SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; B52DD1881BE1F8CD00949AFE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; @@ -2416,7 +2475,7 @@ PRODUCT_NAME = CoreStoreTests; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = "CoreStoreTests/CoreStoreTests-Bridging-Header.h"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -2430,13 +2489,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; SDKROOT = watchos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = 4; }; name = Debug; @@ -2452,13 +2512,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; SDKROOT = watchos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = 4; }; name = Release; diff --git a/CoreStore.xcworkspace/contents.xcworkspacedata b/CoreStore.xcworkspace/contents.xcworkspacedata index 954f208..8ff0a03 100644 --- a/CoreStore.xcworkspace/contents.xcworkspacedata +++ b/CoreStore.xcworkspace/contents.xcworkspacedata @@ -7,7 +7,4 @@ - - diff --git a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj index 0a6ca15..1a19818 100644 --- a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj +++ b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj @@ -36,8 +36,6 @@ B569651C1B30889A0075EE4A /* QueryingResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */; }; B56965291B3582D30075EE4A /* MigrationDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B56965271B3582D30075EE4A /* MigrationDemo.xcdatamodeld */; }; B5E599321B5240F50084BD5F /* OrganismTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */; }; - B5E89ACD1C52929C003B04A9 /* GCDKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9241C202429008147CD /* GCDKit.framework */; }; - B5E89ACE1C52929C003B04A9 /* GCDKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9241C202429008147CD /* GCDKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; }; B5E89AD11C5292A2003B04A9 /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B5EE25851B36E23C0000406B /* OrganismV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE25841B36E23C0000406B /* OrganismV1.swift */; }; @@ -54,7 +52,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - B5E89ACE1C52929C003B04A9 /* GCDKit.framework in Embed Frameworks */, B5E89AD11C5292A2003B04A9 /* CoreStore.framework in Embed Frameworks */, ); name = "Embed Frameworks"; @@ -94,7 +91,6 @@ B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryingResultsViewController.swift; sourceTree = ""; }; B56965281B3582D30075EE4A /* MigrationDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemo.xcdatamodel; sourceTree = ""; }; B5BDC9211C202429008147CD /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B5BDC9241C202429008147CD /* GCDKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = GCDKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OrganismTableViewCell.swift; path = "CoreStoreDemo/MIgrations Demo/OrganismTableViewCell.swift"; sourceTree = SOURCE_ROOT; }; B5EE25801B36E1B00000406B /* MigrationDemoV2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemoV2.xcdatamodel; sourceTree = ""; }; B5EE25841B36E23C0000406B /* OrganismV1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV1.swift; sourceTree = ""; }; @@ -110,7 +106,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B5E89ACD1C52929C003B04A9 /* GCDKit.framework in Frameworks */, B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */, B52977E11B120F8A003D50A5 /* CoreLocation.framework in Frameworks */, B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */, @@ -146,7 +141,6 @@ children = ( B52977E01B120F8A003D50A5 /* CoreLocation.framework */, B5BDC9211C202429008147CD /* CoreStore.framework */, - B5BDC9241C202429008147CD /* GCDKit.framework */, B52977DE1B120F83003D50A5 /* MapKit.framework */, ); name = Frameworks; @@ -272,7 +266,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "John Rommel Estropia"; TargetAttributes = { B54AAD481AF4D26E00848AE0 = { @@ -462,7 +456,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -475,7 +469,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.corestore.demo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/CoreStoreDemo/CoreStoreDemo/AppDelegate.swift b/CoreStoreDemo/CoreStoreDemo/AppDelegate.swift index cae2352..2e0af90 100644 --- a/CoreStoreDemo/CoreStoreDemo/AppDelegate.swift +++ b/CoreStoreDemo/CoreStoreDemo/AppDelegate.swift @@ -18,9 +18,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { - application.statusBarStyle = .LightContent + application.statusBarStyle = .lightContent return true } diff --git a/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/FetchingAndQueryingDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/FetchingAndQueryingDemoViewController.swift index dbb113b..c4aa4c0 100644 --- a/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/FetchingAndQueryingDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/FetchingAndQueryingDemoViewController.swift @@ -19,27 +19,27 @@ private struct Static { SQLiteStore( fileName: "TimeZoneDemo.sqlite", configuration: "FetchingAndQueryingDemo", - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) ) - dataStack.beginSynchronous { (transaction) -> Void in + _ = dataStack.beginSynchronous { (transaction) -> Void in - transaction.deleteAll(From(TimeZone)) + transaction.deleteAll(From()) - for name in NSTimeZone.knownTimeZoneNames() { + for name in NSTimeZone.knownTimeZoneNames { let rawTimeZone = NSTimeZone(name: name)! - let cachedTimeZone = transaction.create(Into(TimeZone)) + let cachedTimeZone = transaction.create(Into()) cachedTimeZone.name = rawTimeZone.name cachedTimeZone.abbreviation = rawTimeZone.abbreviation ?? "" cachedTimeZone.secondsFromGMT = Int32(rawTimeZone.secondsFromGMT) - cachedTimeZone.hasDaylightSavingTime = rawTimeZone.daylightSavingTime + cachedTimeZone.hasDaylightSavingTime = rawTimeZone.isDaylightSavingTime cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset } - transaction.commitAndWait() + _ = transaction.commitAndWait() } return dataStack @@ -53,7 +53,7 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo // MARK: UIViewController - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) @@ -67,27 +67,27 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo let alert = UIAlertController( title: "Fetch and Query Demo", message: "This demo shows how to execute fetches and queries.\n\nEach menu item executes and displays a preconfigured fetch/query.", - preferredStyle: .Alert + preferredStyle: .alert ) - alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil)) - self.presentViewController(alert, animated: true, completion: nil) + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) + self.present(alert, animated: true, completion: nil) } - override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - super.prepareForSegue(segue, sender: sender) + super.prepare(for: segue, sender: sender) - if let indexPath = sender as? NSIndexPath { + if let indexPath = sender as? IndexPath { - switch segue.destinationViewController { + switch segue.destination { case let controller as FetchingResultsViewController: let item = self.fetchingItems[indexPath.row] - controller.setTimeZones(item.fetch(), title: item.title) + controller.set(timeZones: item.fetch(), title: item.title) case let controller as QueryingResultsViewController: let item = self.queryingItems[indexPath.row] - controller.setValue(item.query(), title: item.title) + controller.set(value: item.query(), title: item.title) default: break @@ -98,14 +98,14 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo // MARK: UITableViewDataSource - func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch self.segmentedControl?.selectedSegmentIndex { - case Section.Fetching.rawValue?: + case Section.fetching.rawValue?: return self.fetchingItems.count - case Section.Querying.rawValue?: + case Section.querying.rawValue?: return self.queryingItems.count default: @@ -113,16 +113,16 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo } } - func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell")! + let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")! switch self.segmentedControl?.selectedSegmentIndex { - case Section.Fetching.rawValue?: + case Section.fetching.rawValue?: cell.textLabel?.text = self.fetchingItems[indexPath.row].title - case Section.Querying.rawValue?: + case Section.querying.rawValue?: cell.textLabel?.text = self.queryingItems[indexPath.row].title default: @@ -135,17 +135,17 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo // MARK: UITableViewDelegate - func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - tableView.deselectRowAtIndexPath(indexPath, animated: true) + tableView.deselectRow(at: indexPath, animated: true) switch self.segmentedControl?.selectedSegmentIndex { - case Section.Fetching.rawValue?: - self.performSegueWithIdentifier("FetchingResultsViewController", sender: indexPath) + case Section.fetching.rawValue?: + self.performSegue(withIdentifier: "FetchingResultsViewController", sender: indexPath) - case Section.Querying.rawValue?: - self.performSegueWithIdentifier("QueryingResultsViewController", sender: indexPath) + case Section.querying.rawValue?: + self.performSegue(withIdentifier: "QueryingResultsViewController", sender: indexPath) default: break @@ -157,8 +157,8 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo private enum Section: Int { - case Fetching - case Querying + case fetching + case querying } private let fetchingItems = [ @@ -167,8 +167,8 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo fetch: { () -> [TimeZone] in return Static.timeZonesStack.fetchAll( - From(TimeZone), - OrderBy(.Ascending("name")) + From(), + OrderBy(.ascending(#keyPath(TimeZone.name))) )! } ), @@ -177,9 +177,9 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo fetch: { () -> [TimeZone] in return Static.timeZonesStack.fetchAll( - From(TimeZone), - Where("%K BEGINSWITH[c] %@", "name", "Asia"), - OrderBy(.Ascending("secondsFromGMT")) + From(), + Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "Asia"), + OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT))) )! } ), @@ -188,10 +188,10 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo fetch: { () -> [TimeZone] in return Static.timeZonesStack.fetchAll( - From(TimeZone), - Where("%K BEGINSWITH[c] %@", "name", "America") - || Where("%K BEGINSWITH[c] %@", "name", "Europe"), - OrderBy(.Ascending("secondsFromGMT")) + From(), + Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "America") + || Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "Europe"), + OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT))) )! } ), @@ -200,9 +200,9 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo fetch: { () -> [TimeZone] in return Static.timeZonesStack.fetchAll( - From(TimeZone), - !Where("%K BEGINSWITH[c] %@", "name", "America"), - OrderBy(.Ascending("secondsFromGMT")) + From(), + !Where("%K BEGINSWITH[c] %@", #keyPath(TimeZone.name), "America"), + OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT))) )! } ), @@ -211,9 +211,9 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo fetch: { () -> [TimeZone] in return Static.timeZonesStack.fetchAll( - From(TimeZone), + From(), Where("hasDaylightSavingTime", isEqualTo: true), - OrderBy(.Ascending("name")) + OrderBy(.ascending(#keyPath(TimeZone.name))) )! } ) @@ -222,60 +222,60 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo private let queryingItems = [ ( title: "Number of Time Zones", - query: { () -> AnyObject in + query: { () -> Any in return Static.timeZonesStack.queryValue( - From(TimeZone), - Select(.Count("name")) + From(), + Select(.count(#keyPath(TimeZone.name))) )! } ), ( title: "Abbreviation For Tokyo's Time Zone", - query: { () -> AnyObject in + query: { () -> Any in return Static.timeZonesStack.queryValue( - From(TimeZone), - Select("abbreviation"), - Where("%K ENDSWITH[c] %@", "name", "Tokyo") + From(), + Select(#keyPath(TimeZone.abbreviation)), + Where("%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo") )! } ), ( title: "All Abbreviations", - query: { () -> AnyObject in + query: { () -> Any in return Static.timeZonesStack.queryAttributes( - From(TimeZone), - Select("name", "abbreviation"), - OrderBy(.Ascending("name")) + From(), + Select(#keyPath(TimeZone.name), #keyPath(TimeZone.abbreviation)), + OrderBy(.ascending(#keyPath(TimeZone.name))) )! } ), ( title: "Number of Countries per Time Zone", - query: { () -> AnyObject in + query: { () -> Any in return Static.timeZonesStack.queryAttributes( - From(TimeZone), - Select(.Count("abbreviation"), "abbreviation"), - GroupBy("abbreviation"), - OrderBy(.Ascending("secondsFromGMT"), .Ascending("name")) + From(), + Select(.count(#keyPath(TimeZone.abbreviation)), #keyPath(TimeZone.abbreviation)), + GroupBy(#keyPath(TimeZone.abbreviation)), + OrderBy(.ascending(#keyPath(TimeZone.secondsFromGMT)), .ascending(#keyPath(TimeZone.name))) )! } ), ( title: "Number of Countries with Summer Time", - query: { () -> AnyObject in + query: { () -> Any in return Static.timeZonesStack.queryAttributes( - From(TimeZone), + From(), Select( - .Count("hasDaylightSavingTime", As: "numberOfCountries"), - "hasDaylightSavingTime" + .count(#keyPath(TimeZone.hasDaylightSavingTime), as: "numberOfCountries"), + #keyPath(TimeZone.hasDaylightSavingTime) ), - GroupBy("hasDaylightSavingTime"), - OrderBy(.Descending("hasDaylightSavingTime")) + GroupBy(#keyPath(TimeZone.hasDaylightSavingTime)), + OrderBy(.descending(#keyPath(TimeZone.hasDaylightSavingTime))) )! } ) @@ -286,7 +286,7 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo @IBOutlet dynamic weak var segmentedControl: UISegmentedControl? @IBOutlet dynamic weak var tableView: UITableView? - @IBAction dynamic func segmentedControlValueChanged(sender: AnyObject?) { + @IBAction dynamic func segmentedControlValueChanged(_ sender: AnyObject?) { self.tableView?.reloadData() } diff --git a/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/FetchingResultsViewController.swift b/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/FetchingResultsViewController.swift index 17003e9..d49c5f2 100644 --- a/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/FetchingResultsViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/FetchingResultsViewController.swift @@ -14,7 +14,7 @@ class FetchingResultsViewController: UITableViewController { // MARK: Public - func setTimeZones(timeZones: [TimeZone]?, title: String) { + func set(timeZones: [TimeZone]?, title: String) { self.timeZones += timeZones ?? [] self.sectionTitle = title @@ -36,14 +36,14 @@ class FetchingResultsViewController: UITableViewController { // MARK: UITableViewDataSource - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.timeZones.count } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath) + let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath) let timeZone = self.timeZones[indexPath.row] cell.textLabel?.text = timeZone.name @@ -55,7 +55,7 @@ class FetchingResultsViewController: UITableViewController { // MARK: UITableViewDelegate - override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return self.sectionTitle } diff --git a/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/QueryingResultsViewController.swift b/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/QueryingResultsViewController.swift index 3399187..2f01c73 100644 --- a/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/QueryingResultsViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Fetching and Querying Demo/QueryingResultsViewController.swift @@ -12,23 +12,23 @@ class QueryingResultsViewController: UITableViewController { // MARK: Public - func setValue(value: AnyObject?, title: String) { + func set(value: Any?, title: String) { switch value { - case (let array as [AnyObject])?: - self.values = array.map { (item: AnyObject) -> (title: String, detail: String) in + case (let array as [Any])?: + self.values = array.map { (item: Any) -> (title: String, detail: String) in ( - title: item.description, - detail: String(reflecting: item.dynamicType) + title: String(describing: item), + detail: String(reflecting: type(of: item)) ) } case let item?: self.values = [ ( - title: item.description, - detail: String(reflecting: item.dynamicType) + title: String(describing: item), + detail: String(reflecting: type(of: item)) ) ] @@ -55,14 +55,14 @@ class QueryingResultsViewController: UITableViewController { // MARK: UITableViewDataSource - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.values.count } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath) + let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath) let value = self.values[indexPath.row] @@ -75,7 +75,7 @@ class QueryingResultsViewController: UITableViewController { // MARK: UITableViewDelegate - override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return self.sectionTitle } diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ListObserverDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ListObserverDemoViewController.swift index 1a5121d..5a84b73 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ListObserverDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ListObserverDemoViewController.swift @@ -14,17 +14,17 @@ private struct Static { enum Filter: String { - case All = "All Colors" - case Light = "Light Colors" - case Dark = "Dark Colors" + case all = "All Colors" + case light = "Light Colors" + case dark = "Dark Colors" func next() -> Filter { switch self { - case All: return .Light - case Light: return .Dark - case Dark: return .All + case .all: return .light + case .light: return .dark + case .dark: return .all } } @@ -32,14 +32,14 @@ private struct Static { switch self { - case .All: return Where(true) - case .Light: return Where("brightness >= 0.9") - case .Dark: return Where("brightness <= 0.4") + case .all: return Where(true) + case .light: return Where("%K >= %@", #keyPath(Palette.brightness), 0.9) + case .dark: return Where("%K <= %@", #keyPath(Palette.brightness), 0.4) } } } - static var filter = Filter.All { + static var filter = Filter.all { didSet { @@ -53,14 +53,14 @@ private struct Static { SQLiteStore( fileName: "ColorsDemo.sqlite", configuration: "ObservingDemo", - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) ) return CoreStore.monitorSectionedList( - From(Palette), - SectionBy("colorName"), - OrderBy(.Ascending("hue")) + From(), + SectionBy(#keyPath(Palette.colorName)), + OrderBy(.ascending(#keyPath(Palette.hue))) ) }() } @@ -86,9 +86,9 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver let navigationItem = self.navigationItem navigationItem.leftBarButtonItems = [ - self.editButtonItem(), + self.editButtonItem, UIBarButtonItem( - barButtonSystemItem: .Trash, + barButtonSystemItem: .trash, target: self, action: #selector(self.resetBarButtonItemTouched(_:)) ) @@ -96,13 +96,13 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver let filterBarButton = UIBarButtonItem( title: Static.filter.rawValue, - style: .Plain, + style: .plain, target: self, action: #selector(self.filterBarButtonItemTouched(_:)) ) navigationItem.rightBarButtonItems = [ UIBarButtonItem( - barButtonSystemItem: .Add, + barButtonSystemItem: .add, target: self, action: #selector(self.addBarButtonItemTouched(_:)) ), @@ -112,14 +112,14 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver Static.palettes.addObserver(self) - self.setTableEnabled(!Static.palettes.isPendingRefetch) + self.setTable(enabled: !Static.palettes.isPendingRefetch) } - override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - super.prepareForSegue(segue, sender: sender) + super.prepare(for: segue, sender: sender) - switch (segue.identifier, segue.destinationViewController, sender) { + switch (segue.identifier, segue.destination, sender) { case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as Palette): destinationViewController.palette = palette @@ -132,19 +132,19 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver // MARK: UITableViewDataSource - override func numberOfSectionsInTableView(tableView: UITableView) -> Int { + override func numberOfSections(in tableView: UITableView) -> Int { return Static.palettes.numberOfSections() } - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return Static.palettes.numberOfObjectsInSection(section) } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCellWithIdentifier("PaletteTableViewCell") as! PaletteTableViewCell + let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell let palette = Static.palettes[indexPath] cell.colorView?.backgroundColor = palette.color @@ -156,21 +156,21 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver // MARK: UITableViewDelegate - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - tableView.deselectRowAtIndexPath(indexPath, animated: true) + tableView.deselectRow(at: indexPath, animated: true) - self.performSegueWithIdentifier( - "ObjectObserverDemoViewController", + self.performSegue( + withIdentifier: "ObjectObserverDemoViewController", sender: Static.palettes[indexPath] ) } - override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { switch editingStyle { - case .Delete: + case .delete: let palette = Static.palettes[indexPath] CoreStore.beginAsynchronous{ (transaction) -> Void in @@ -183,7 +183,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver } } - override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return Static.palettes.sectionInfoAtIndex(section).name } @@ -191,44 +191,44 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver // MARK: ListObserver - func listMonitorWillChange(monitor: ListMonitor) { + func listMonitorWillChange(_ monitor: ListMonitor) { self.tableView.beginUpdates() } - func listMonitorDidChange(monitor: ListMonitor) { + func listMonitorDidChange(_ monitor: ListMonitor) { self.tableView.endUpdates() } - func listMonitorWillRefetch(monitor: ListMonitor) { + func listMonitorWillRefetch(_ monitor: ListMonitor) { - self.setTableEnabled(false) + self.setTable(enabled: false) } - func listMonitorDidRefetch(monitor: ListMonitor) { + func listMonitorDidRefetch(_ monitor: ListMonitor) { self.filterBarButton?.title = Static.filter.rawValue self.tableView.reloadData() - self.setTableEnabled(true) + self.setTable(enabled: true) } // MARK: ListObjectObserver - func listMonitor(monitor: ListMonitor, didInsertObject object: Palette, toIndexPath indexPath: NSIndexPath) { + func listMonitor(_ monitor: ListMonitor, didInsertObject object: Palette, toIndexPath indexPath: IndexPath) { - self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) + self.tableView.insertRows(at: [indexPath], with: .automatic) } - func listMonitor(monitor: ListMonitor, didDeleteObject object: Palette, fromIndexPath indexPath: NSIndexPath) { + func listMonitor(_ monitor: ListMonitor, didDeleteObject object: Palette, fromIndexPath indexPath: IndexPath) { - self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) + self.tableView.deleteRows(at: [indexPath], with: .automatic) } - func listMonitor(monitor: ListMonitor, didUpdateObject object: Palette, atIndexPath indexPath: NSIndexPath) { + func listMonitor(_ monitor: ListMonitor, didUpdateObject object: Palette, atIndexPath indexPath: IndexPath) { - if let cell = self.tableView.cellForRowAtIndexPath(indexPath) as? PaletteTableViewCell { + if let cell = self.tableView.cellForRow(at: indexPath) as? PaletteTableViewCell { let palette = Static.palettes[indexPath] cell.colorView?.backgroundColor = palette.color @@ -236,23 +236,24 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver } } - func listMonitor(monitor: ListMonitor, didMoveObject object: Palette, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + func listMonitor(_ monitor: ListMonitor, didMoveObject object: Palette, fromIndexPath: IndexPath, toIndexPath: IndexPath) { - self.tableView.deleteRowsAtIndexPaths([fromIndexPath], withRowAnimation: .Automatic) - self.tableView.insertRowsAtIndexPaths([toIndexPath], withRowAnimation: .Automatic) + self.tableView.deleteRows(at: [fromIndexPath], with: .automatic) + self.tableView.insertRows(at: [toIndexPath], with: .automatic) } // MARK: ListSectionObserver - func listMonitor(monitor: ListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { + func listMonitor(_ monitor: ListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { - self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Automatic) + self.tableView.insertSections(IndexSet(integer: sectionIndex), with: .automatic) } - func listMonitor(monitor: ListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { + + func listMonitor(_ monitor: ListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { - self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Automatic) + self.tableView.deleteSections(IndexSet(integer: sectionIndex), with: .automatic) } @@ -260,43 +261,43 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver private var filterBarButton: UIBarButtonItem? - @IBAction private dynamic func resetBarButtonItemTouched(sender: AnyObject?) { + @IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) { CoreStore.beginAsynchronous { (transaction) -> Void in - transaction.deleteAll(From(Palette)) + transaction.deleteAll(From()) transaction.commit() } } - @IBAction private dynamic func filterBarButtonItemTouched(sender: AnyObject?) { + @IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) { Static.filter = Static.filter.next() } - @IBAction private dynamic func addBarButtonItemTouched(sender: AnyObject?) { + @IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) { CoreStore.beginAsynchronous { (transaction) -> Void in - let palette = transaction.create(Into(Palette)) + let palette = transaction.create(Into()) palette.setInitialValues() transaction.commit() } } - private func setTableEnabled(enabled: Bool) { + private func setTable(enabled: Bool) { - UIView.animateWithDuration( - 0.2, + UIView.animate( + withDuration: 0.2, delay: 0, - options: .BeginFromCurrentState, + options: .beginFromCurrentState, animations: { () -> Void in if let tableView = self.tableView { tableView.alpha = enabled ? 1.0 : 0.5 - tableView.userInteractionEnabled = enabled + tableView.isUserInteractionEnabled = enabled } }, completion: nil diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift index 09145ec..b887d3f 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObjectObserverDemoViewController.swift @@ -50,7 +50,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { required init?(coder aDecoder: NSCoder) { - if let palette = CoreStore.fetchOne(From(Palette), OrderBy(.Ascending("hue"))) { + if let palette = CoreStore.fetchOne(From(), OrderBy(.ascending(#keyPath(Palette.hue)))) { self.monitor = CoreStore.monitorObject(palette) } @@ -58,13 +58,13 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { CoreStore.beginSynchronous { (transaction) -> Void in - let palette = transaction.create(Into(Palette)) + let palette = transaction.create(Into(Palette.self)) palette.setInitialValues() - transaction.commitAndWait() + _ = transaction.commitAndWait() } - let palette = CoreStore.fetchOne(From(Palette), OrderBy(.Ascending("hue")))! + let palette = CoreStore.fetchOne(From(), OrderBy(.ascending(#keyPath(Palette.hue))))! self.monitor = CoreStore.monitorObject(palette) } @@ -85,24 +85,24 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { // MARK: ObjectObserver - func objectMonitor(monitor: ObjectMonitor, didUpdateObject object: Palette, changedPersistentKeys: Set) { + func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: Palette, changedPersistentKeys: Set) { self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys) } - func objectMonitor(monitor: ObjectMonitor, didDeleteObject object: Palette) { + func objectMonitor(_ monitor: ObjectMonitor, didDeleteObject object: Palette) { - self.navigationItem.rightBarButtonItem?.enabled = false + self.navigationItem.rightBarButtonItem?.isEnabled = false self.colorNameLabel?.alpha = 0.3 self.colorView?.alpha = 0.3 self.hsbLabel?.text = "Deleted" - self.hsbLabel?.textColor = UIColor.redColor() + self.hsbLabel?.textColor = UIColor.red - self.hueSlider?.enabled = false - self.saturationSlider?.enabled = false - self.brightnessSlider?.enabled = false + self.hueSlider?.isEnabled = false + self.saturationSlider?.isEnabled = false + self.brightnessSlider?.isEnabled = false } @@ -118,7 +118,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { @IBOutlet weak var saturationSlider: UISlider? @IBOutlet weak var brightnessSlider: UISlider? - @IBAction dynamic func hueSliderValueDidChange(sender: AnyObject?) { + @IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) { let hue = self.hueSlider?.value ?? 0 CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in @@ -131,7 +131,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { } } - @IBAction dynamic func saturationSliderValueDidChange(sender: AnyObject?) { + @IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) { let saturation = self.saturationSlider?.value ?? 0 CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in @@ -144,7 +144,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { } } - @IBAction dynamic func brightnessSliderValueDidChange(sender: AnyObject?) { + @IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) { let brightness = self.brightnessSlider?.value ?? 0 CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in @@ -157,7 +157,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { } } - @IBAction dynamic func deleteBarButtonTapped(sender: AnyObject?) { + @IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) { CoreStore.beginAsynchronous { [weak self] (transaction) -> Void in @@ -166,7 +166,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { } } - func reloadPaletteInfo(palette: Palette, changedKeys: Set?) { + func reloadPaletteInfo(_ palette: Palette, changedKeys: Set?) { self.colorNameLabel?.text = palette.colorName @@ -176,15 +176,15 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver { self.hsbLabel?.text = palette.colorText - if changedKeys == nil || changedKeys?.contains("hue") == true { + if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.hue)) == true { self.hueSlider?.value = Float(palette.hue) } - if changedKeys == nil || changedKeys?.contains("saturation") == true { + if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.saturation)) == true { self.saturationSlider?.value = palette.saturation } - if changedKeys == nil || changedKeys?.contains("brightness") == true { + if changedKeys == nil || changedKeys?.contains(#keyPath(Palette.brightness)) == true { self.brightnessSlider?.value = palette.brightness } diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObserversViewController.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObserversViewController.swift index 3ae0f43..a59e085 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObserversViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/ObserversViewController.swift @@ -15,16 +15,16 @@ class ObserversViewController: UIViewController { // MARK: UIViewController - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let alert = UIAlertController( title: "Observers Demo", message: "This demo shows how to observe changes to a list of objects. The top and bottom view controllers both observe a single shared \"ListMonitor\" instance.\n\nTap on a row to see how to observe changes made to a single object using a \"ObjectMonitor\".", - preferredStyle: .Alert + preferredStyle: .alert ) - alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil)) - self.presentViewController(alert, animated: true, completion: nil) + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) + self.present(alert, animated: true, completion: nil) } } diff --git a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift index c6c2fa8..5dfb3ef 100644 --- a/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift +++ b/CoreStoreDemo/CoreStoreDemo/List and Object Observers Demo/Palette.swift @@ -24,7 +24,7 @@ class Palette: NSManagedObject { get { - let KVCKey = "colorName" + let KVCKey = #keyPath(Palette.colorName) if let colorName = self.accessValueForKVCKey(KVCKey) as? String { return colorName @@ -49,7 +49,7 @@ class Palette: NSManagedObject { } set { - self.setValue(newValue, forKVCKey: "colorName") + self.setValue(newValue, forKVCKey: #keyPath(Palette.colorName)) } } diff --git a/CoreStoreDemo/CoreStoreDemo/Loggers Demo/CustomLoggerViewController.swift b/CoreStoreDemo/CoreStoreDemo/Loggers Demo/CustomLoggerViewController.swift index a0c3c10..9864f18 100644 --- a/CoreStoreDemo/CoreStoreDemo/Loggers Demo/CustomLoggerViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Loggers Demo/CustomLoggerViewController.swift @@ -8,7 +8,6 @@ import UIKit import CoreStore -import GCDKit // MARK: - CustomLoggerViewController @@ -34,47 +33,47 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger { CoreStore.logger = self } - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let alert = UIAlertController( title: "Logger Demo", message: "This demo shows how to plug-in any logging framework to CoreStore.\n\nThe view controller implements CoreStoreLogger and appends all logs to the text view.", - preferredStyle: .Alert + preferredStyle: .alert ) - alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil)) - self.presentViewController(alert, animated: true, completion: nil) + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) + self.present(alert, animated: true, completion: nil) } // MARK: CoreStoreLogger - func log(level level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { - GCDQueue.Main.async { [weak self] in + DispatchQueue.main.async { [weak self] in let levelString: String switch level { - case .Trace: levelString = "Trace" - case .Notice: levelString = "Notice" - case .Warning: levelString = "Warning" - case .Fatal: levelString = "Fatal" + case .trace: levelString = "Trace" + case .notice: levelString = "Notice" + case .warning: levelString = "Warning" + case .fatal: levelString = "Fatal" } - self?.textView?.insertText("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Log:\(levelString)] \(message)\n\n") + self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Log:\(levelString)] \(message)\n\n") } } - func log(error error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { - GCDQueue.Main.async { [weak self] in + DispatchQueue.main.async { [weak self] in - self?.textView?.insertText("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Error] \(message): \(error)\n\n") + self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Error] \(message): \(error)\n\n") } } - func assert(@autoclosure condition: () -> Bool, @autoclosure message: () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { if condition() { @@ -82,9 +81,9 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger { } let messageString = message() - GCDQueue.Main.async { [weak self] in + DispatchQueue.main.async { [weak self] in - self?.textView?.insertText("\((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Assert] \(messageString)\n\n") + self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Assert] \(messageString)\n\n") } } @@ -94,14 +93,14 @@ class CustomLoggerViewController: UIViewController, CoreStoreLogger { @IBOutlet dynamic weak var textView: UITextView? @IBOutlet dynamic weak var segmentedControl: UISegmentedControl? - @IBAction dynamic func segmentedControlValueChanged(sender: AnyObject?) { + @IBAction dynamic func segmentedControlValueChanged(_ sender: AnyObject?) { switch self.segmentedControl?.selectedSegmentIndex { case 0?: self.dataStack.beginAsynchronous { (transaction) -> Void in - transaction.create(Into(Palette)) + _ = transaction.create(Into()) } case 1?: diff --git a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift index c5a42be..4e823b7 100644 --- a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift @@ -12,7 +12,7 @@ import CoreStore // MARK: - MigrationsDemoViewController -class MigrationsDemoViewController: UIViewController { +class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewDataSource, UITableViewDelegate { // MARK: UIViewController @@ -22,28 +22,28 @@ class MigrationsDemoViewController: UIViewController { if let segmentedControl = self.segmentedControl { - for (index, model) in self.models.enumerate() { + for (index, model) in self.models.enumerated() { segmentedControl.setTitle( model.label, - forSegmentAtIndex: index + forSegmentAt: index ) } } - self.setDataStack(nil, model: nil, scrollToSelection: false) + self.set(dataStack: nil, model: nil, scrollToSelection: false) } - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let alert = UIAlertController( title: "Migrations Demo", message: "This demo shows how to run progressive migrations and how to support multiple model versions in a single project.\n\nThe persistent store contains 10000 organisms, which gain/lose properties when the migration evolves/devolves them.\n\nYou can use the \"mutate\" button to change an organism's properties then migrate to a different model to see how its value gets affected.", - preferredStyle: .Alert + preferredStyle: .alert ) - alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil)) - self.presentViewController(alert, animated: true, completion: nil) + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) + self.present(alert, animated: true, completion: nil) let modelMetadata = withExtendedLifetime(DataStack(modelName: "MigrationDemo")) { @@ -72,6 +72,71 @@ class MigrationsDemoViewController: UIViewController { self.selectModelVersion(modelMetadata) } + // MARK: ListObserver + + func listMonitorWillChange(_ monitor: ListMonitor) { } + + func listMonitorDidChange(_ monitor: ListMonitor) { + + if self.lastSelectedIndexPath == nil, + let numberOfObjectsInSection = self.listMonitor?.numberOfObjectsInSection(0), + numberOfObjectsInSection > 0 { + + self.tableView?.reloadData() + self.setSelectedIndexPath(IndexPath(row: 0, section: 0), scrollToSelection: false) + } + else { + + self.updateDisplay(reloadData: true, scrollToSelection: true, animated: true) + } + } + + // MARK: UITableViewDataSource + + @objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + + return self.listMonitor?.numberOfObjectsInSection(0) ?? 0 + } + + @objc dynamic func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView.dequeueReusableCell(withIdentifier: "OrganismTableViewCell", for: indexPath) as! OrganismTableViewCell + + let dna = (self.listMonitor?[indexPath] as? OrganismProtocol)?.dna.description ?? "" + cell.dnaLabel?.text = "DNA: \(dna)" + cell.mutateButtonHandler = { [weak self] _ -> Void in + + guard let `self` = self, + let dataStack = self.dataStack, + let organism = self.listMonitor?[indexPath] else { + + return + } + + self.setSelectedIndexPath(indexPath, scrollToSelection: false) + self.setEnabled(false) + dataStack.beginAsynchronous { [weak self] (transaction) -> Void in + + let organism = transaction.edit(organism) as! OrganismProtocol + organism.mutate() + + transaction.commit { _ -> Void in + + self?.setEnabled(true) + } + } + } + return cell + } + + + // MARK: UITableViewDelegate + + @objc dynamic func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + self.setSelectedIndexPath(indexPath, scrollToSelection: false) + } + // MARK: Private @@ -113,13 +178,13 @@ class MigrationsDemoViewController: UIViewController { return self._dataStack } - private var _lastSelectedIndexPath: NSIndexPath? - private var lastSelectedIndexPath: NSIndexPath? { + private var _lastSelectedIndexPath: IndexPath? + private var lastSelectedIndexPath: IndexPath? { return self._lastSelectedIndexPath } - private func setSelectedIndexPath(indexPath: NSIndexPath, scrollToSelection: Bool) { + private func setSelectedIndexPath(_ indexPath: IndexPath, scrollToSelection: Bool) { self._lastSelectedIndexPath = indexPath self.updateDisplay(reloadData: false, scrollToSelection: scrollToSelection, animated: true) @@ -132,7 +197,7 @@ class MigrationsDemoViewController: UIViewController { @IBOutlet private dynamic weak var progressView: UIProgressView? @IBOutlet private dynamic weak var tableView: UITableView? - @IBAction private dynamic func segmentedControlValueChanged(sender: AnyObject?) { + @IBAction private dynamic func segmentedControlValueChanged(_ sender: AnyObject?) { guard let index = self.segmentedControl?.selectedSegmentIndex else { @@ -142,14 +207,14 @@ class MigrationsDemoViewController: UIViewController { self.selectModelVersion(self.models[index]) } - private func selectModelVersion(model: ModelMetadata) { + private func selectModelVersion(_ model: ModelMetadata) { if self.dataStack?.modelVersion == model.version { return } - self.setDataStack(nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack + self.set(dataStack: nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack let dataStack = DataStack( modelName: "MigrationDemo", @@ -166,18 +231,17 @@ class MigrationsDemoViewController: UIViewController { return } - guard case .Success = result else { + guard case .success = result else { self.setEnabled(true) return } - self.setDataStack(dataStack, model: model, scrollToSelection: true) + self.set(dataStack: dataStack, model: model, scrollToSelection: true) let count = dataStack.queryValue( From(model.entityType), - Select(.Count("dna")) - ) + Select(.count(#keyPath(OrganismV1.dna))))! if count > 0 { self.setEnabled(true) @@ -218,39 +282,39 @@ class MigrationsDemoViewController: UIViewController { } } - private func setEnabled(enabled: Bool) { + private func setEnabled(_ enabled: Bool) { - UIView.animateWithDuration( - 0.2, + UIView.animate( + withDuration: 0.2, delay: 0, - options: .BeginFromCurrentState, + options: .beginFromCurrentState, animations: { () -> Void in let navigationItem = self.navigationItem - navigationItem.leftBarButtonItem?.enabled = enabled - navigationItem.rightBarButtonItem?.enabled = enabled + navigationItem.leftBarButtonItem?.isEnabled = enabled + navigationItem.rightBarButtonItem?.isEnabled = enabled navigationItem.hidesBackButton = !enabled - self.segmentedControl?.enabled = enabled + self.segmentedControl?.isEnabled = enabled if let tableView = self.tableView { tableView.alpha = enabled ? 1.0 : 0.5 - tableView.userInteractionEnabled = enabled + tableView.isUserInteractionEnabled = enabled } }, completion: nil ) } - private func setDataStack(dataStack: DataStack?, model: ModelMetadata?, scrollToSelection: Bool) { + private func set(dataStack: DataStack?, model: ModelMetadata?, scrollToSelection: Bool) { if let dataStack = dataStack, let model = model { - self.segmentedControl?.selectedSegmentIndex = self.models.map { $0.version }.indexOf(model.version)! + self.segmentedControl?.selectedSegmentIndex = self.models.map { $0.version }.index(of: model.version)! self._dataStack = dataStack - let listMonitor = dataStack.monitorList(From(model.entityType), OrderBy(.Descending("dna"))) + let listMonitor = dataStack.monitorList(From(model.entityType), OrderBy(.descending("dna"))) listMonitor.addObserver(self) self._listMonitor = listMonitor @@ -258,7 +322,7 @@ class MigrationsDemoViewController: UIViewController { if listMonitor.numberOfObjectsInSection(0) > 0 { - self.setSelectedIndexPath(NSIndexPath(forRow: 0, inSection: 0), scrollToSelection: true) + self.setSelectedIndexPath(IndexPath(row: 0, section: 0), scrollToSelection: true) } } } @@ -272,14 +336,14 @@ class MigrationsDemoViewController: UIViewController { self.updateDisplay(reloadData: true, scrollToSelection: scrollToSelection, animated: false) } - private func reloadTableHeaderWithProgress(progress: NSProgress) { + private func reloadTableHeaderWithProgress(_ progress: Progress) { self.progressView?.setProgress(Float(progress.fractionCompleted), animated: true) - self.titleLabel?.text = "Migrating: \(progress.localizedDescription)" - self.organismLabel?.text = "Progressive step \(progress.localizedAdditionalDescription)" + self.titleLabel?.text = "Migrating: \(progress.localizedDescription ?? "")" + self.organismLabel?.text = "Progressive step \(progress.localizedAdditionalDescription ?? "")" } - private func updateDisplay(reloadData reloadData: Bool, scrollToSelection: Bool, animated: Bool) { + private func updateDisplay(reloadData: Bool, scrollToSelection: Bool, animated: Bool) { var lines = [String]() var organismType = "" @@ -287,14 +351,14 @@ class MigrationsDemoViewController: UIViewController { for property in organism.entity.properties { - let value: AnyObject = organism.valueForKey(property.name) ?? NSNull() + let value = organism.value(forKey: property.name) ?? NSNull() lines.append("\(property.name): \(value)") } organismType = organism.entity.managedObjectClassName } self.titleLabel?.text = organismType - self.organismLabel?.text = lines.joinWithSeparator("\n") + self.organismLabel?.text = lines.joined(separator: "\n") self.progressView?.progress = 0 self.headerContainer?.setNeedsLayout() @@ -311,87 +375,13 @@ class MigrationsDemoViewController: UIViewController { tableView.layoutIfNeeded() - if let indexPath = self.lastSelectedIndexPath where indexPath.row < tableView.numberOfRowsInSection(0) { + if let indexPath = self.lastSelectedIndexPath, + indexPath.row < tableView.numberOfRows(inSection: 0) { - tableView.selectRowAtIndexPath(indexPath, + tableView.selectRow(at: indexPath, animated: scrollToSelection && animated, - scrollPosition: scrollToSelection ? .Middle : .None + scrollPosition: scrollToSelection ? .middle : .none ) } } } - - -// MARK: - MigrationsDemoViewController: ListObserver - -extension MigrationsDemoViewController: ListObserver { - - // MARK: ListObserver - - func listMonitorWillChange(monitor: ListMonitor) { } - - func listMonitorDidChange(monitor: ListMonitor) { - - if self.lastSelectedIndexPath == nil && self.listMonitor?.numberOfObjectsInSection(0) > 0 { - - self.tableView?.reloadData() - self.setSelectedIndexPath(NSIndexPath(forRow: 0, inSection: 0), scrollToSelection: false) - } - else { - - self.updateDisplay(reloadData: true, scrollToSelection: true, animated: true) - } - } -} - - -// MARK: - MigrationsDemoViewController: UITableViewDataSource, UITableViewDelegate - -extension MigrationsDemoViewController: UITableViewDataSource, UITableViewDelegate { - - // MARK: UITableViewDataSource - - @objc dynamic func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - - return self.listMonitor?.numberOfObjectsInSection(0) ?? 0 - } - - @objc dynamic func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { - - let cell = tableView.dequeueReusableCellWithIdentifier("OrganismTableViewCell", forIndexPath: indexPath) as! OrganismTableViewCell - - let dna = (self.listMonitor?[indexPath] as? OrganismProtocol)?.dna.description ?? "" - cell.dnaLabel?.text = "DNA: \(dna)" - cell.mutateButtonHandler = { [weak self] _ -> Void in - - guard let `self` = self, - let dataStack = self.dataStack, - let organism = self.listMonitor?[indexPath] else { - - return - } - - self.setSelectedIndexPath(indexPath, scrollToSelection: false) - self.setEnabled(false) - dataStack.beginAsynchronous { [weak self] (transaction) -> Void in - - let organism = transaction.edit(organism) as! OrganismProtocol - organism.mutate() - - transaction.commit { _ -> Void in - - self?.setEnabled(true) - } - } - } - return cell - } - - - // MARK: UITableViewDelegate - - @objc dynamic func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - - self.setSelectedIndexPath(indexPath, scrollToSelection: false) - } -} diff --git a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismProtocol.swift b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismProtocol.swift index 45e1271..918939e 100644 --- a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismProtocol.swift +++ b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismProtocol.swift @@ -13,4 +13,4 @@ protocol OrganismProtocol: class { var dna: Int64 { get set } func mutate() -} \ No newline at end of file +} diff --git a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismTableViewCell.swift b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismTableViewCell.swift index 285d057..94996b0 100644 --- a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismTableViewCell.swift +++ b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismTableViewCell.swift @@ -15,7 +15,7 @@ class OrganismTableViewCell: UITableViewCell { var mutateButtonHandler: (() -> Void)? - @IBAction dynamic func mutateButtonTouchUpInside(sender: UIButton?) { + @IBAction dynamic func mutateButtonTouchUpInside(_ sender: UIButton?) { self.mutateButtonHandler?() } diff --git a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismV2ToV3MigrationPolicy.swift b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismV2ToV3MigrationPolicy.swift index 6a16682..cbb9cbe 100644 --- a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismV2ToV3MigrationPolicy.swift +++ b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/OrganismV2ToV3MigrationPolicy.swift @@ -10,14 +10,20 @@ import CoreData class OrganismV2ToV3MigrationPolicy: NSEntityMigrationPolicy { - override func createDestinationInstancesForSourceInstance(sInstance: NSManagedObject, entityMapping mapping: NSEntityMapping, manager: NSMigrationManager) throws { + override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws { - try super.createDestinationInstancesForSourceInstance(sInstance, entityMapping: mapping, manager: manager) + try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager) - for dInstance in manager.destinationInstancesForEntityMappingNamed(mapping.name, sourceInstances: [sInstance]) { + for dInstance in manager.destinationInstances(forEntityMappingName: mapping.name, sourceInstances: [sInstance]) { - dInstance.setValue(false, forKey: "hasVertebrae") - dInstance.setValue(sInstance.valueForKey("numberOfFlippers"), forKey: "numberOfLimbs") + dInstance.setValue( + false, + forKey: #keyPath(OrganismV3.hasVertebrae) + ) + dInstance.setValue( + sInstance.value(forKey: #keyPath(OrganismV2.numberOfFlippers)), + forKey: #keyPath(OrganismV3.numberOfLimbs) + ) } } } diff --git a/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemo.xcdatamodel/contents b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemo.xcdatamodel/contents index b1f5a2e..0bfb5f2 100644 --- a/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemo.xcdatamodel/contents +++ b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemo.xcdatamodel/contents @@ -1,9 +1,9 @@ - + - - - + + + diff --git a/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV2.xcdatamodel/contents b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV2.xcdatamodel/contents index dd6f661..cc9fb18 100644 --- a/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV2.xcdatamodel/contents +++ b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV2.xcdatamodel/contents @@ -1,10 +1,10 @@ - + - - - - + + + + diff --git a/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV3.xcdatamodel/contents b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV3.xcdatamodel/contents index 48509e6..04a1049 100644 --- a/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV3.xcdatamodel/contents +++ b/CoreStoreDemo/CoreStoreDemo/MigrationDemo.xcdatamodeld/MigrationDemoV3.xcdatamodel/contents @@ -1,11 +1,11 @@ - + - - - - - + + + + + diff --git a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/StackSetupDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/StackSetupDemoViewController.swift index e6bdbbf..7dbbed2 100644 --- a/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/StackSetupDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Stack Setup Demo/StackSetupDemoViewController.swift @@ -22,20 +22,20 @@ private struct Static { SQLiteStore( fileName: "AccountsDemo_FB_Male.sqlite", configuration: maleConfiguration, - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) ) try! dataStack.addStorageAndWait( SQLiteStore( fileName: "AccountsDemo_FB_Female.sqlite", configuration: femaleConfiguration, - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) ) - dataStack.beginSynchronous { (transaction) -> Void in + _ = dataStack.beginSynchronous { (transaction) -> Void in - transaction.deleteAll(From(UserAccount)) + transaction.deleteAll(From()) let account1 = transaction.create(Into(maleConfiguration)) account1.accountType = "Facebook" @@ -47,7 +47,7 @@ private struct Static { account2.name = "Jane Doe HCD" account2.friends = 314 - transaction.commitAndWait() + _ = transaction.commitAndWait() } return dataStack @@ -60,20 +60,20 @@ private struct Static { SQLiteStore( fileName: "AccountsDemo_TW_Male.sqlite", configuration: maleConfiguration, - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) ) try! dataStack.addStorageAndWait( SQLiteStore( fileName: "AccountsDemo_TW_Female.sqlite", configuration: femaleConfiguration, - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) ) - dataStack.beginSynchronous { (transaction) -> Void in + _ = dataStack.beginSynchronous { (transaction) -> Void in - transaction.deleteAll(From(UserAccount)) + transaction.deleteAll(From()) let account1 = transaction.create(Into(maleConfiguration)) account1.accountType = "Twitter" @@ -85,7 +85,7 @@ private struct Static { account2.name = "#janedoe_hcd" account2.friends = 100 - transaction.commitAndWait() + _ = transaction.commitAndWait() } return dataStack @@ -100,53 +100,53 @@ private struct Static { class StackSetupDemoViewController: UITableViewController { let accounts = [ - Static.facebookStack.fetchAll(From(UserAccount)) ?? [], - Static.twitterStack.fetchAll(From(UserAccount)) ?? [] + Static.facebookStack.fetchAll(From(UserAccount.self)) ?? [], + Static.twitterStack.fetchAll(From(UserAccount.self)) ?? [] ] // MARK: UIViewController - override func viewWillAppear(animated: Bool) { + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.tableView.reloadData() - let indexPath = NSIndexPath(forRow: 0, inSection: 0) - self.tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None) - self.updateDetailsWithAccount(self.accounts[indexPath.section][indexPath.row]) + let indexPath = IndexPath(row: 0, section: 0) + self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none) + self.updateDetails(account: self.accounts[indexPath.section][indexPath.row]) } - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let alert = UIAlertController( title: "Setup Demo", message: "This demo shows how to initialize 2 DataStacks with 2 configurations each, for a total of 4 SQLite files, each with 1 instance of a \"UserAccount\" entity.", - preferredStyle: .Alert + preferredStyle: .alert ) - alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil)) - self.presentViewController(alert, animated: true, completion: nil) + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) + self.present(alert, animated: true, completion: nil) } // MARK: UITableViewDataSource - override func numberOfSectionsInTableView(tableView: UITableView) -> Int { + override func numberOfSections(in tableView: UITableView) -> Int { return self.accounts.count } - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.accounts[section].count } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell")! + let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")! let account = self.accounts[indexPath.section][indexPath.row] cell.textLabel?.text = account.name @@ -158,13 +158,13 @@ class StackSetupDemoViewController: UITableViewController { // MARK: UITableViewDelegate - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let account = self.accounts[indexPath.section][indexPath.row] - self.updateDetailsWithAccount(account) + self.updateDetails(account: account) } - override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { switch section { @@ -188,7 +188,7 @@ class StackSetupDemoViewController: UITableViewController { @IBOutlet private dynamic weak var nameLabel: UILabel? @IBOutlet private dynamic weak var friendsLabel: UILabel? - private func updateDetailsWithAccount(account: UserAccount) { + private func updateDetails(account: UserAccount) { self.accountTypeLabel?.text = account.accountType self.nameLabel?.text = account.name diff --git a/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift index 03d1ba3..469dd10 100644 --- a/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/Transactions Demo/TransactionsDemoViewController.swift @@ -11,7 +11,6 @@ import CoreLocation import MapKit import AddressBookUI import CoreStore -import GCDKit private struct Static { @@ -22,21 +21,21 @@ private struct Static { SQLiteStore( fileName: "PlaceDemo.sqlite", configuration: "TransactionsDemo", - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) ) - var place = CoreStore.fetchOne(From(Place)) + var place = CoreStore.fetchOne(From()) if place == nil { - CoreStore.beginSynchronous { (transaction) -> Void in + _ = CoreStore.beginSynchronous { (transaction) -> Void in - let place = transaction.create(Into(Place)) + let place = transaction.create(Into()) place.setInitialValues() - transaction.commitAndWait() + _ = transaction.commitAndWait() } - place = CoreStore.fetchOne(From(Place)) + place = CoreStore.fetchOne(From()) } return CoreStore.monitorObject(place!) @@ -71,33 +70,33 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec Static.placeController.addObserver(self) self.navigationItem.rightBarButtonItem = UIBarButtonItem( - barButtonSystemItem: .Refresh, + barButtonSystemItem: .refresh, target: self, action: #selector(self.refreshButtonTapped(_:)) ) } - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let alert = UIAlertController( title: "Transactions Demo", message: "This demo shows how to use the 3 types of transactions to save updates: synchronous, asynchronous, and unsafe.\n\nTap and hold on the map to change the pin location.", - preferredStyle: .Alert + preferredStyle: .alert ) - alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil)) - self.presentViewController(alert, animated: true, completion: nil) + alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) + self.present(alert, animated: true, completion: nil) } - override func viewWillAppear(animated: Bool) { + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if let mapView = self.mapView, let place = Static.placeController.object { mapView.addAnnotation(place) - mapView.setCenterCoordinate(place.coordinate, animated: false) + mapView.setCenter(place.coordinate, animated: false) mapView.selectAnnotation(place, animated: false) } } @@ -105,14 +104,14 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec // MARK: MKMapViewDelegate - func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? { + func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { let identifier = "MKAnnotationView" - var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView + var annotationView: MKPinAnnotationView! = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView if annotationView == nil { annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier) - annotationView.enabled = true + annotationView.isEnabled = true annotationView.canShowCallout = true annotationView.animatesDrop = true } @@ -127,28 +126,28 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec // MARK: ObjectObserver - func objectMonitor(monitor: ObjectMonitor, willUpdateObject object: Place) { + func objectMonitor(_ monitor: ObjectMonitor, willUpdateObject object: Place) { // none } - func objectMonitor(monitor: ObjectMonitor, didUpdateObject object: Place, changedPersistentKeys: Set) { + func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: Place, changedPersistentKeys: Set) { if let mapView = self.mapView { - mapView.removeAnnotations(mapView.annotations ?? []) + mapView.removeAnnotations(mapView.annotations) mapView.addAnnotation(object) - mapView.setCenterCoordinate(object.coordinate, animated: true) + mapView.setCenter(object.coordinate, animated: true) mapView.selectAnnotation(object, animated: true) - if changedPersistentKeys.contains("latitude") || changedPersistentKeys.contains("longitude") { + if changedPersistentKeys.contains(#keyPath(Place.latitude)) || changedPersistentKeys.contains(#keyPath(Place.longitude)) { - self.geocodePlace(object) + self.geocode(place: object) } } } - func objectMonitor(monitor: ObjectMonitor, didDeleteObject object: Place) { + func objectMonitor(_ monitor: ObjectMonitor, didDeleteObject object: Place) { // none } @@ -160,13 +159,15 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec @IBOutlet weak var mapView: MKMapView? - @IBAction dynamic func longPressGestureRecognized(sender: AnyObject?) { + @IBAction dynamic func longPressGestureRecognized(_ sender: AnyObject?) { - if let mapView = self.mapView, let gesture = sender as? UILongPressGestureRecognizer where gesture.state == .Began { + if let mapView = self.mapView, + let gesture = sender as? UILongPressGestureRecognizer, + gesture.state == .began { - let coordinate = mapView.convertPoint( - gesture.locationInView(mapView), - toCoordinateFromView: mapView + let coordinate = mapView.convert( + gesture.location(in: mapView), + toCoordinateFrom: mapView ) CoreStore.beginAsynchronous { (transaction) -> Void in @@ -177,17 +178,17 @@ class TransactionsDemoViewController: UIViewController, MKMapViewDelegate, Objec } } - @IBAction dynamic func refreshButtonTapped(sender: AnyObject?) { + @IBAction dynamic func refreshButtonTapped(_ sender: AnyObject?) { - CoreStore.beginSynchronous { (transaction) -> Void in + _ = CoreStore.beginSynchronous { (transaction) -> Void in let place = transaction.edit(Static.placeController.object) place?.setInitialValues() - transaction.commitAndWait() + _ = transaction.commitAndWait() } } - func geocodePlace(place: Place) { + func geocode(place: Place) { let transaction = CoreStore.beginUnsafe() diff --git a/CoreStoreTests/BaseTests/BaseTestCase.swift b/CoreStoreTests/BaseTests/BaseTestCase.swift index f3f1fe3..4ce253e 100644 --- a/CoreStoreTests/BaseTests/BaseTestCase.swift +++ b/CoreStoreTests/BaseTests/BaseTestCase.swift @@ -36,11 +36,12 @@ class BaseTestCase: XCTestCase { // MARK: Internal @nonobjc - func prepareStack(configurations configurations: [String?] = [nil], @noescape _ closure: (dataStack: DataStack) -> T) -> T { + @discardableResult + func prepareStack(configurations: [String?] = [nil], _ closure: (_ dataStack: DataStack) -> T) -> T { let stack = DataStack( modelName: "Model", - bundle: NSBundle(forClass: self.dynamicType) + bundle: Bundle(for: type(of: self)) ) do { @@ -49,10 +50,10 @@ class BaseTestCase: XCTestCase { try stack.addStorageAndWait( SQLiteStore( fileURL: SQLiteStore.defaultRootDirectory - .URLByAppendingPathComponent(NSUUID().UUIDString)! - .URLByAppendingPathComponent("\(self.dynamicType)_\(($0 ?? "-null-")).sqlite")!, + .appendingPathComponent(UUID().uuidString) + .appendingPathComponent("\(type(of: self))_\(($0 ?? "-null-")).sqlite"), configuration: $0, - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) ) } @@ -61,11 +62,11 @@ class BaseTestCase: XCTestCase { XCTFail(error.coreStoreDumpString) } - return closure(dataStack: stack) + return closure(stack) } @nonobjc - func expectLogger(expectations: [TestLogger.Expectation], @noescape closure: () -> T) -> T { + func expectLogger(_ expectations: [TestLogger.Expectation], closure: () -> T) -> T { CoreStore.logger = TestLogger(self.prepareLoggerExpectations(expectations)) defer { @@ -77,18 +78,18 @@ class BaseTestCase: XCTestCase { } @nonobjc - func expectLogger(expectations: [TestLogger.Expectation: XCTestExpectation]) { + func expectLogger(_ expectations: [TestLogger.Expectation: XCTestExpectation]) { CoreStore.logger = TestLogger(expectations) } @nonobjc - func prepareLoggerExpectations(expectations: [TestLogger.Expectation]) -> [TestLogger.Expectation: XCTestExpectation] { + func prepareLoggerExpectations(_ expectations: [TestLogger.Expectation]) -> [TestLogger.Expectation: XCTestExpectation] { var testExpectations: [TestLogger.Expectation: XCTestExpectation] = [:] for expectation in expectations { - testExpectations[expectation] = self.expectationWithDescription("Logger Expectation: \(expectation)") + testExpectations[expectation] = self.expectation(description: "Logger Expectation: \(expectation)") } return testExpectations } @@ -96,13 +97,13 @@ class BaseTestCase: XCTestCase { @nonobjc func checkExpectationsImmediately() { - self.waitForExpectationsWithTimeout(0, handler: nil) + self.waitForExpectations(timeout: 0, handler: { _ in }) } @nonobjc func waitAndCheckExpectations() { - self.waitForExpectationsWithTimeout(10, handler: nil) + self.waitForExpectations(timeout: 10, handler: {_ in }) } // MARK: XCTestCase @@ -126,7 +127,7 @@ class BaseTestCase: XCTestCase { private func deleteStores() { - _ = try? NSFileManager.defaultManager().removeItemAtURL(SQLiteStore.defaultRootDirectory) + _ = try? FileManager.default.removeItem(at: SQLiteStore.defaultRootDirectory) } } @@ -137,11 +138,11 @@ class TestLogger: CoreStoreLogger { enum Expectation { - case LogWarning - case LogFatal - case LogError - case AssertionFailure - case FatalError + case logWarning + case logFatal + case logError + case assertionFailure + case fatalError } init(_ expectations: [Expectation: XCTestExpectation]) { @@ -152,33 +153,33 @@ class TestLogger: CoreStoreLogger { // MARK: CoreStoreLogger - func log(level level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { switch level { - case .Warning: self.fulfill(.LogWarning) - case .Fatal: self.fulfill(.LogFatal) + case .warning: self.fulfill(.logWarning) + case .fatal: self.fulfill(.logFatal) default: break } } - func log(error error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { - self.fulfill(.LogError) + self.fulfill(.logError) } - func assert(@autoclosure condition: () -> Bool, @autoclosure message: () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { if condition() { return } - self.fulfill(.AssertionFailure) + self.fulfill(.assertionFailure) } - func abort(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { + func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) { - self.fulfill(.FatalError) + self.fulfill(.fatalError) } @@ -186,7 +187,7 @@ class TestLogger: CoreStoreLogger { private var expectations: [Expectation: XCTestExpectation] - private func fulfill(expectation: Expectation) { + private func fulfill(_ expectation: Expectation) { if let instance = self.expectations[expectation] { diff --git a/CoreStoreTests/BaseTests/BaseTestDataTestCase.swift b/CoreStoreTests/BaseTests/BaseTestDataTestCase.swift index 64140d1..3f707e8 100644 --- a/CoreStoreTests/BaseTests/BaseTestDataTestCase.swift +++ b/CoreStoreTests/BaseTests/BaseTestDataTestCase.swift @@ -17,22 +17,22 @@ import CoreStore class BaseTestDataTestCase: BaseTestCase { @nonobjc - let dateFormatter: NSDateFormatter = { + let dateFormatter: DateFormatter = { - let formatter = NSDateFormatter() - formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") - formatter.timeZone = NSTimeZone(name: "UTC") - formatter.calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(identifier: "UTC") + formatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian) formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ" return formatter }() @nonobjc - func prepareTestDataForStack(stack: DataStack, configurations: [String?] = [nil]) { + func prepareTestDataForStack(_ stack: DataStack, configurations: [String?] = [nil]) { stack.beginSynchronous { (transaction) in - for (configurationIndex, configuration) in configurations.enumerate() { + for (configurationIndex, configuration) in configurations.enumerated() { let configurationOrdinal = configurationIndex + 1 if configuration == nil || configuration == "Config1" { @@ -40,16 +40,16 @@ class BaseTestDataTestCase: BaseTestCase { for idIndex in 1 ... 5 { let object = transaction.create(Into(configuration)) - object.testEntityID = NSNumber(integer: (configurationOrdinal * 100) + idIndex) + object.testEntityID = NSNumber(value: (configurationOrdinal * 100) + idIndex) - object.testNumber = idIndex - object.testDate = self.dateFormatter.dateFromString("2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z") - object.testBoolean = (idIndex % 2) == 1 + object.testNumber = NSNumber(value: idIndex) + object.testDate = self.dateFormatter.date(from: "2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z") + object.testBoolean = NSNumber(value: (idIndex % 2) == 1) object.testDecimal = NSDecimalNumber(string: "\(idIndex)") let string = "\(configuration ?? "nil"):TestEntity1:\(idIndex)" object.testString = string - object.testData = (string as NSString).dataUsingEncoding(NSUTF8StringEncoding) + object.testData = (string as NSString).data(using: String.Encoding.utf8.rawValue) } } if configuration == nil || configuration == "Config2" { @@ -57,20 +57,20 @@ class BaseTestDataTestCase: BaseTestCase { for idIndex in 1 ... 5 { let object = transaction.create(Into(configuration)) - object.testEntityID = NSNumber(integer: (configurationOrdinal * 200) + idIndex) + object.testEntityID = NSNumber(value: (configurationOrdinal * 200) + idIndex) - object.testNumber = idIndex - object.testDate = self.dateFormatter.dateFromString("2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z") - object.testBoolean = (idIndex % 2) == 1 + object.testNumber = NSNumber(value: idIndex) + object.testDate = self.dateFormatter.date(from: "2000-\(configurationOrdinal)-\(idIndex)T00:00:00Z") + object.testBoolean = NSNumber(value: (idIndex % 2) == 1) object.testDecimal = NSDecimalNumber(string: "\(idIndex)") let string = "\(configuration ?? "nil"):TestEntity2:\(idIndex)" object.testString = string - object.testData = (string as NSString).dataUsingEncoding(NSUTF8StringEncoding) + object.testData = (string as NSString).data(using: String.Encoding.utf8.rawValue) } } } - transaction.commitAndWait() + _ = transaction.commitAndWait() } } } diff --git a/CoreStoreTests/BridgingTests.m b/CoreStoreTests/BridgingTests.m index 04c2efa..77c18df 100644 --- a/CoreStoreTests/BridgingTests.m +++ b/CoreStoreTests/BridgingTests.m @@ -233,5 +233,37 @@ } [self waitForExpectationsWithTimeout:10 handler:nil]; } + +#if TARGET_OS_IOS || TARGET_OS_WATCHOS || TARGET_OS_TV + +- (void)test_ThatDataStacks_CanCreateCustomFetchedResultsControllers { + + [CSCoreStore + setDefaultStack:[[CSDataStack alloc] + initWithModelName:@"Model" + bundle:[NSBundle bundleForClass:[self class]] + versionChain:nil]]; + [CSCoreStore + addInMemoryStorageAndWait:[CSInMemoryStore new] + error:nil]; + NSFetchedResultsController *controller = + [[CSCoreStore defaultStack] + createFetchedResultsControllerFrom:CSFromClass([TestEntity1 class]) + sectionBy:[CSSectionBy keyPath:CSKeyPath(TestEntity1, testString)] + fetchClauses:@[CSWhereFormat(@"%K > %d", CSKeyPath(TestEntity1, testEntityID), 100), + CSOrderByKeys(CSSortAscending(CSKeyPath(TestEntity1, testString)), nil), + CSTweakRequest(^(NSFetchRequest *fetchRequest) { fetchRequest.fetchLimit = 10; })]]; + + XCTAssertNotNil(controller); + XCTAssertEqualObjects(controller.fetchRequest.entity.managedObjectClassName, [[TestEntity1 class] description]); + XCTAssertEqualObjects(controller.sectionNameKeyPath, CSKeyPath(TestEntity1, testString)); + XCTAssertEqualObjects(controller.fetchRequest.predicate, + CSWhereFormat(@"%K > %d", CSKeyPath(TestEntity1, testEntityID), 100).predicate); + XCTAssertEqualObjects(controller.fetchRequest.sortDescriptors, + CSOrderByKeys(CSSortAscending(CSKeyPath(TestEntity1, testString)), nil).sortDescriptors); + XCTAssertEqual(controller.fetchRequest.fetchLimit, 10); +} + +#endif @end diff --git a/CoreStoreTests/ConvenienceTests.swift b/CoreStoreTests/ConvenienceTests.swift new file mode 100644 index 0000000..6fea9ba --- /dev/null +++ b/CoreStoreTests/ConvenienceTests.swift @@ -0,0 +1,94 @@ +// +// ConvenienceTests.swift +// CoreStore +// +// Copyright © 2016 John Rommel Estropia +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +@testable +import CoreStore + + +#if os(iOS) || os(watchOS) || os(tvOS) + +// MARK: - ConvenienceTests + +class ConvenienceTests: BaseTestCase { + + @objc + dynamic func test_ThatDataStacks_CanCreateFetchedResultsControllers() { + + self.prepareStack { (stack) in + + let controller = stack.createFetchedResultsController( + From(), + SectionBy(#keyPath(TestEntity1.testString)), + Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100), + OrderBy(.ascending(#keyPath(TestEntity1.testString))), + Tweak { $0.fetchLimit = 10 } + ) + XCTAssertEqual(controller.managedObjectContext, stack.mainContext) + XCTAssertEqual(controller.fetchRequest.entity?.managedObjectClassName, NSStringFromClass(TestEntity1.self)) + XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString)) + XCTAssertEqual( + controller.fetchRequest.sortDescriptors!, + OrderBy(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors + ) + XCTAssertEqual( + controller.fetchRequest.predicate, + Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate + ) + XCTAssertEqual(controller.fetchRequest.fetchLimit, 10) + } + } + + @objc + dynamic func test_ThatUnsafeDataTransactions_CanCreateFetchedResultsControllers() { + + self.prepareStack { (stack) in + + _ = withExtendedLifetime(stack.beginUnsafe()) { (transaction: UnsafeDataTransaction) in + + let controller = transaction.createFetchedResultsController( + From(), + SectionBy(#keyPath(TestEntity1.testString)), + Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100), + OrderBy(.ascending(#keyPath(TestEntity1.testString))), + Tweak { $0.fetchLimit = 10 } + ) + XCTAssertEqual(controller.managedObjectContext, transaction.context) + XCTAssertEqual(controller.fetchRequest.entity?.managedObjectClassName, NSStringFromClass(TestEntity1.self)) + XCTAssertEqual(controller.sectionNameKeyPath, #keyPath(TestEntity1.testString)) + XCTAssertEqual( + controller.fetchRequest.sortDescriptors!, + OrderBy(.ascending(#keyPath(TestEntity1.testString))).sortDescriptors + ) + XCTAssertEqual( + controller.fetchRequest.predicate, + Where("%@ > %d", #keyPath(TestEntity1.testEntityID), 100).predicate + ) + XCTAssertEqual(controller.fetchRequest.fetchLimit, 10) + } + } + } +} + +#endif diff --git a/CoreStoreTests/ErrorTests.swift b/CoreStoreTests/ErrorTests.swift index 006d430..ac294fd 100644 --- a/CoreStoreTests/ErrorTests.swift +++ b/CoreStoreTests/ErrorTests.swift @@ -36,33 +36,33 @@ final class ErrorTests: XCTestCase { @objc dynamic func test_ThatUnknownErrors_BridgeCorrectly() { - let error = CoreStoreError.Unknown + let error = CoreStoreError.unknown XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain) - XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.UnknownError.rawValue) + XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.unknownError.rawValue) let userInfo: NSDictionary = [:] let objcError = error.bridgeToObjectiveC XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError.code, CoreStoreErrorCode.UnknownError.rawValue) - XCTAssertEqual(objcError.userInfo, userInfo) + XCTAssertEqual(objcError.code, CoreStoreErrorCode.unknownError.rawValue) + XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError2.code, CoreStoreErrorCode.UnknownError.rawValue) - XCTAssertEqual(objcError2.userInfo, userInfo) + XCTAssertEqual(objcError2.code, CoreStoreErrorCode.unknownError.rawValue) + XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) } @objc dynamic func test_ThatDifferentStorageExistsAtURLErrors_BridgeCorrectly() { - let dummyURL = NSURL(string: "file:///test1/test2.sqlite")! + let dummyURL = URL(string: "file:///test1/test2.sqlite")! - let error = CoreStoreError.DifferentStorageExistsAtURL(existingPersistentStoreURL: dummyURL) + let error = CoreStoreError.differentStorageExistsAtURL(existingPersistentStoreURL: dummyURL) XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain) - XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue) + XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue) let userInfo: NSDictionary = [ "existingPersistentStoreURL": dummyURL @@ -70,27 +70,27 @@ final class ErrorTests: XCTestCase { let objcError = error.bridgeToObjectiveC XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError.code, CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue) - XCTAssertEqual(objcError.userInfo, userInfo) + XCTAssertEqual(objcError.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue) + XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError2.code, CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue) - XCTAssertEqual(objcError2.userInfo, userInfo) + XCTAssertEqual(objcError2.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue) + XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) } @objc dynamic func test_ThatMappingModelNotFoundErrors_BridgeCorrectly() { - let dummyURL = NSURL(string: "file:///test1/test2.sqlite")! + let dummyURL = URL(string: "file:///test1/test2.sqlite")! - let model = NSManagedObjectModel.fromBundle(NSBundle(forClass: self.dynamicType), modelName: "Model") + let model = NSManagedObjectModel.fromBundle(Bundle(for: type(of: self)), modelName: "Model") let version = "1.0.0" - let error = CoreStoreError.MappingModelNotFound(localStoreURL: dummyURL, targetModel: model, targetModelVersion: version) + let error = CoreStoreError.mappingModelNotFound(localStoreURL: dummyURL, targetModel: model, targetModelVersion: version) XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain) - XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.MappingModelNotFound.rawValue) + XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.mappingModelNotFound.rawValue) let userInfo: NSDictionary = [ "localStoreURL": dummyURL, @@ -100,24 +100,24 @@ final class ErrorTests: XCTestCase { let objcError = error.bridgeToObjectiveC XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError.code, CoreStoreErrorCode.MappingModelNotFound.rawValue) - XCTAssertEqual(objcError.userInfo, userInfo) + XCTAssertEqual(objcError.code, CoreStoreErrorCode.mappingModelNotFound.rawValue) + XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError2.code, CoreStoreErrorCode.MappingModelNotFound.rawValue) - XCTAssertEqual(objcError2.userInfo, userInfo) + XCTAssertEqual(objcError2.code, CoreStoreErrorCode.mappingModelNotFound.rawValue) + XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) } @objc dynamic func test_ThatProgressiveMigrationRequiredErrors_BridgeCorrectly() { - let dummyURL = NSURL(string: "file:///test1/test2.sqlite")! + let dummyURL = URL(string: "file:///test1/test2.sqlite")! - let error = CoreStoreError.ProgressiveMigrationRequired(localStoreURL: dummyURL) + let error = CoreStoreError.progressiveMigrationRequired(localStoreURL: dummyURL) XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain) - XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue) + XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue) let userInfo: NSDictionary = [ "localStoreURL": dummyURL @@ -125,14 +125,14 @@ final class ErrorTests: XCTestCase { let objcError = error.bridgeToObjectiveC XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError.code, CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue) - XCTAssertEqual(objcError.userInfo, userInfo) + XCTAssertEqual(objcError.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue) + XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError2.code, CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue) - XCTAssertEqual(objcError2.userInfo, userInfo) + XCTAssertEqual(objcError2.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue) + XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) } @objc @@ -144,12 +144,12 @@ final class ErrorTests: XCTestCase { userInfo: [ "key1": "value1", "key2": 2, - "key3": NSDate() + "key3": Date() ] ) let error = CoreStoreError(internalError) XCTAssertEqual((error as NSError).domain, CoreStoreErrorDomain) - XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.InternalError.rawValue) + XCTAssertEqual((error as NSError).code, CoreStoreErrorCode.internalError.rawValue) let userInfo: NSDictionary = [ "NSError": internalError @@ -157,13 +157,13 @@ final class ErrorTests: XCTestCase { let objcError = error.bridgeToObjectiveC XCTAssertEqual(error, objcError.bridgeToSwift) XCTAssertEqual(objcError.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError.code, CoreStoreErrorCode.InternalError.rawValue) - XCTAssertEqual(objcError.userInfo, userInfo) + XCTAssertEqual(objcError.code, CoreStoreErrorCode.internalError.rawValue) + XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo) let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC XCTAssertEqual(error, objcError2.bridgeToSwift) XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain) - XCTAssertEqual(objcError2.code, CoreStoreErrorCode.InternalError.rawValue) - XCTAssertEqual(objcError2.userInfo, userInfo) + XCTAssertEqual(objcError2.code, CoreStoreErrorCode.internalError.rawValue) + XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo) } } diff --git a/CoreStoreTests/FetchTests.swift b/CoreStoreTests/FetchTests.swift index 4b03fd0..7963785 100644 --- a/CoreStoreTests/FetchTests.swift +++ b/CoreStoreTests/FetchTests.swift @@ -24,7 +24,6 @@ // import XCTest -import GCDKit @testable import CoreStore @@ -42,9 +41,9 @@ final class FetchTests: BaseTestDataTestCase { self.prepareTestDataForStack(stack, configurations: configurations) - let from = From(TestEntity1) + let from = From() let fetchClauses: [FetchClause] = [ - OrderBy(.Ascending("testEntityID")) + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses)! do { @@ -70,7 +69,7 @@ final class FetchTests: BaseTestDataTestCase { } do { - let fetchExpectation = self.expectationWithDescription("fetch") + let fetchExpectation = self.expectation(description: "fetch") var existing1: TestEntity1? stack.beginSynchronous { (transaction) in @@ -89,7 +88,7 @@ final class FetchTests: BaseTestDataTestCase { } do { - let fetchExpectation = self.expectationWithDescription("fetch") + let fetchExpectation = self.expectation(description: "fetch") stack.beginAsynchronous { (transaction) in let existing1 = transaction.fetchExisting(object) @@ -97,7 +96,7 @@ final class FetchTests: BaseTestDataTestCase { XCTAssertEqual(existing1!.objectID, object.objectID) XCTAssertEqual(existing1!.managedObjectContext, transaction.context) - GCDQueue.Main.async { + DispatchQueue.main.async { let existing2 = stack.fetchExisting(existing1!) XCTAssertNotNil(existing2) @@ -120,9 +119,9 @@ final class FetchTests: BaseTestDataTestCase { self.prepareTestDataForStack(stack, configurations: configurations) - let from = From(TestEntity1) + let from = From() let fetchClauses: [FetchClause] = [ - OrderBy(.Ascending("testEntityID")) + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = stack.fetchAll(from, fetchClauses)! do { @@ -163,7 +162,7 @@ final class FetchTests: BaseTestDataTestCase { } do { - let fetchExpectation = self.expectationWithDescription("fetch") + let fetchExpectation = self.expectation(description: "fetch") var existing1 = [TestEntity1]() stack.beginSynchronous { (transaction) in @@ -192,7 +191,7 @@ final class FetchTests: BaseTestDataTestCase { } do { - let fetchExpectation = self.expectationWithDescription("fetch") + let fetchExpectation = self.expectation(description: "fetch") stack.beginAsynchronous { (transaction) in let existing1 = transaction.fetchExisting(objects) @@ -204,7 +203,7 @@ final class FetchTests: BaseTestDataTestCase { XCTAssertEqual(object.managedObjectContext, transaction.context) } - GCDQueue.Main.async { + DispatchQueue.main.async { let existing2 = stack.fetchExisting(existing1) XCTAssertEqual( @@ -233,12 +232,12 @@ final class FetchTests: BaseTestDataTestCase { do { - let from = From(TestEntity1) + let from = From() do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -251,8 +250,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -265,8 +264,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -281,8 +280,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -295,8 +294,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -309,8 +308,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -325,16 +324,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] - let object = self.expectLogger([.LogWarning]) { + let object = self.expectLogger([.logWarning]) { stack.fetchOne(from, fetchClauses) } XCTAssertNil(object) - let objectID = self.expectLogger([.LogWarning]) { + let objectID = self.expectLogger([.logWarning]) { stack.fetchObjectID(from, fetchClauses) } @@ -343,16 +342,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] - let object = self.expectLogger([.LogWarning]) { + let object = self.expectLogger([.logWarning]) { stack.fetchOne(from, fetchClauses) } XCTAssertNil(object) - let objectID = self.expectLogger([.LogWarning]) { + let objectID = self.expectLogger([.logWarning]) { stack.fetchObjectID(from, fetchClauses) } @@ -372,12 +371,12 @@ final class FetchTests: BaseTestDataTestCase { do { - let from = From(TestEntity1) + let from = From() do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -390,8 +389,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -404,8 +403,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -420,8 +419,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -434,8 +433,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -448,8 +447,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -464,8 +463,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -478,8 +477,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -492,8 +491,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -508,16 +507,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] - let object = self.expectLogger([.LogWarning]) { + let object = self.expectLogger([.logWarning]) { stack.fetchOne(from, fetchClauses) } XCTAssertNil(object) - let objectID = self.expectLogger([.LogWarning]) { + let objectID = self.expectLogger([.logWarning]) { stack.fetchObjectID(from, fetchClauses) } @@ -526,16 +525,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] - let object = self.expectLogger([.LogWarning]) { + let object = self.expectLogger([.logWarning]) { stack.fetchOne(from, fetchClauses) } XCTAssertNil(object) - let objectID = self.expectLogger([.LogWarning]) { + let objectID = self.expectLogger([.logWarning]) { stack.fetchObjectID(from, fetchClauses) } @@ -559,8 +558,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -573,8 +572,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -587,8 +586,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -603,8 +602,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -617,8 +616,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -631,8 +630,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -647,8 +646,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -661,8 +660,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -675,8 +674,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = stack.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -698,12 +697,12 @@ final class FetchTests: BaseTestDataTestCase { do { - let from = From(TestEntity1) + let from = From() do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -728,8 +727,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 5), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -754,8 +753,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -772,8 +771,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -798,8 +797,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 5), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -824,8 +823,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -842,16 +841,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Ascending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] - let objects = self.expectLogger([.LogWarning]) { + let objects = self.expectLogger([.logWarning]) { stack.fetchAll(from, fetchClauses) } XCTAssertNil(objects) - let objectIDs = self.expectLogger([.LogWarning]) { + let objectIDs = self.expectLogger([.logWarning]) { stack.fetchObjectIDs(from, fetchClauses) } @@ -860,16 +859,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("testNumber", isEqualTo: 0), - OrderBy(.Descending("testEntityID")) + Where(#keyPath(TestEntity1.testNumber), isEqualTo: 0), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] - let objects = self.expectLogger([.LogWarning]) { + let objects = self.expectLogger([.logWarning]) { stack.fetchAll(from, fetchClauses) } XCTAssertNil(objects) - let objectIDs = self.expectLogger([.LogWarning]) { + let objectIDs = self.expectLogger([.logWarning]) { stack.fetchObjectIDs(from, fetchClauses) } @@ -889,19 +888,19 @@ final class FetchTests: BaseTestDataTestCase { do { - let from = From(TestEntity1) + let from = From() do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) XCTAssertEqual(objects?.count, 3) XCTAssertEqual( - Set((objects ?? []).map { $0.testNumber!.integerValue }), + Set((objects ?? []).map { $0.testNumber!.intValue }), [4, 5] as Set ) // configuration is ambiguous @@ -916,15 +915,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) XCTAssertEqual(objects?.count, 3) XCTAssertEqual( - Set((objects ?? []).map { $0.testNumber!.integerValue }), + Set((objects ?? []).map { $0.testNumber!.intValue }), [1, 2] as Set ) // configuration is ambiguous @@ -939,8 +938,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -957,8 +956,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -982,8 +981,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -1007,8 +1006,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -1025,8 +1024,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -1050,8 +1049,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -1075,8 +1074,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -1093,15 +1092,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - OrderBy(.Ascending("testEntityID")) + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] - let objects = self.expectLogger([.LogWarning]) { + let objects = self.expectLogger([.logWarning]) { stack.fetchAll(from, fetchClauses) } XCTAssertNil(objects) - let objectIDs = self.expectLogger([.LogWarning]) { + let objectIDs = self.expectLogger([.logWarning]) { stack.fetchObjectIDs(from, fetchClauses) } @@ -1110,15 +1109,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - OrderBy(.Descending("testEntityID")) + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] - let objects = self.expectLogger([.LogWarning]) { + let objects = self.expectLogger([.logWarning]) { stack.fetchAll(from, fetchClauses) } XCTAssertNil(objects) - let objectIDs = self.expectLogger([.LogWarning]) { + let objectIDs = self.expectLogger([.logWarning]) { stack.fetchObjectIDs(from, fetchClauses) } @@ -1142,15 +1141,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) XCTAssertEqual(objects?.count, 3) XCTAssertEqual( - Set((objects ?? []).map { $0.testNumber!.integerValue }), + Set((objects ?? []).map { $0.testNumber!.intValue }), [4, 5] as Set ) // configuration is ambiguous @@ -1165,15 +1164,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) XCTAssertEqual(objects?.count, 3) XCTAssertEqual( - Set((objects ?? []).map { $0.testNumber!.integerValue }), + Set((objects ?? []).map { $0.testNumber!.intValue }), [1, 2] as Set ) // configuration is ambiguous @@ -1188,8 +1187,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -1206,8 +1205,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -1231,8 +1230,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -1256,8 +1255,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -1274,8 +1273,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -1299,8 +1298,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = stack.fetchAll(from, fetchClauses) @@ -1324,8 +1323,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = stack.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -1349,13 +1348,13 @@ final class FetchTests: BaseTestDataTestCase { do { - let from = From(TestEntity1) + let from = From() do { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1365,8 +1364,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K < %@", "testNumber", 5), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1376,8 +1375,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -1390,8 +1389,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1401,8 +1400,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K < %@", "testNumber", 5), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1412,8 +1411,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -1424,24 +1423,24 @@ final class FetchTests: BaseTestDataTestCase { let from = From("Config1") do { - let count = self.expectLogger([.LogWarning]) { + let count = self.expectLogger([.logWarning]) { stack.fetchCount( from, - Where("%K < %@", "testNumber", 4), - OrderBy(.Ascending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) } XCTAssertNil(count) } do { - let count = self.expectLogger([.LogWarning]) { + let count = self.expectLogger([.logWarning]) { stack.fetchCount( from, - Where("testNumber", isEqualTo: 0), - OrderBy(.Descending("testEntityID")) + Where(#keyPath(TestEntity1.testNumber), isEqualTo: 0), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ) } XCTAssertNil(count) @@ -1460,13 +1459,13 @@ final class FetchTests: BaseTestDataTestCase { do { - let from = From(TestEntity1) + let from = From() do { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1476,8 +1475,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1487,8 +1486,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -1501,8 +1500,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1512,8 +1511,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1523,8 +1522,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -1537,8 +1536,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1548,8 +1547,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1559,8 +1558,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -1571,24 +1570,24 @@ final class FetchTests: BaseTestDataTestCase { let from = From("Config2") do { - let count = self.expectLogger([.LogWarning]) { + let count = self.expectLogger([.logWarning]) { stack.fetchCount( from, - Where("%K < %@", "testNumber", 4), - OrderBy(.Ascending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) } XCTAssertNil(count) } do { - let count = self.expectLogger([.LogWarning]) { + let count = self.expectLogger([.logWarning]) { stack.fetchCount( from, - Where("testNumber", isEqualTo: 0), - OrderBy(.Descending("testEntityID")) + Where(#keyPath(TestEntity1.testNumber), isEqualTo: 0), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ) } XCTAssertNil(count) @@ -1612,8 +1611,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1623,8 +1622,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1634,8 +1633,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -1648,8 +1647,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1659,8 +1658,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1670,8 +1669,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -1684,8 +1683,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1695,8 +1694,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -1706,8 +1705,8 @@ final class FetchTests: BaseTestDataTestCase { let count = stack.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -1726,12 +1725,12 @@ final class FetchTests: BaseTestDataTestCase { stack.beginSynchronous { (transaction) in - let from = From(TestEntity1) + let from = From() do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1744,8 +1743,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1758,8 +1757,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -1774,8 +1773,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1788,8 +1787,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1802,8 +1801,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -1818,16 +1817,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] - let object = self.expectLogger([.LogWarning]) { + let object = self.expectLogger([.logWarning]) { transaction.fetchOne(from, fetchClauses) } XCTAssertNil(object) - let objectID = self.expectLogger([.LogWarning]) { + let objectID = self.expectLogger([.logWarning]) { transaction.fetchObjectID(from, fetchClauses) } @@ -1836,16 +1835,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] - let object = self.expectLogger([.LogWarning]) { + let object = self.expectLogger([.logWarning]) { transaction.fetchOne(from, fetchClauses) } XCTAssertNil(object) - let objectID = self.expectLogger([.LogWarning]) { + let objectID = self.expectLogger([.logWarning]) { transaction.fetchObjectID(from, fetchClauses) } @@ -1865,12 +1864,12 @@ final class FetchTests: BaseTestDataTestCase { stack.beginSynchronous { (transaction) in - let from = From(TestEntity1) + let from = From() do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1883,8 +1882,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1897,8 +1896,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -1913,8 +1912,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1927,8 +1926,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1941,8 +1940,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -1957,8 +1956,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1971,8 +1970,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -1985,8 +1984,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -2001,16 +2000,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] - let object = self.expectLogger([.LogWarning]) { + let object = self.expectLogger([.logWarning]) { transaction.fetchOne(from, fetchClauses) } XCTAssertNil(object) - let objectID = self.expectLogger([.LogWarning]) { + let objectID = self.expectLogger([.logWarning]) { transaction.fetchObjectID(from, fetchClauses) } @@ -2019,16 +2018,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] - let object = self.expectLogger([.LogWarning]) { + let object = self.expectLogger([.logWarning]) { transaction.fetchOne(from, fetchClauses) } XCTAssertNil(object) - let objectID = self.expectLogger([.LogWarning]) { + let objectID = self.expectLogger([.logWarning]) { transaction.fetchObjectID(from, fetchClauses) } @@ -2052,8 +2051,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -2066,8 +2065,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -2080,8 +2079,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -2096,8 +2095,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -2110,8 +2109,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -2124,8 +2123,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -2140,8 +2139,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -2154,8 +2153,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Descending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNotNil(object) @@ -2168,8 +2167,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let object = transaction.fetchOne(from, fetchClauses) XCTAssertNil(object) @@ -2191,12 +2190,12 @@ final class FetchTests: BaseTestDataTestCase { stack.beginSynchronous { (transaction) in - let from = From(TestEntity1) + let from = From() do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2221,8 +2220,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 5), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2247,8 +2246,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -2265,8 +2264,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2291,8 +2290,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 5), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2317,8 +2316,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -2335,16 +2334,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 4), - OrderBy(.Ascending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] - let objects = self.expectLogger([.LogWarning]) { + let objects = self.expectLogger([.logWarning]) { transaction.fetchAll(from, fetchClauses) } XCTAssertNil(objects) - let objectIDs = self.expectLogger([.LogWarning]) { + let objectIDs = self.expectLogger([.logWarning]) { transaction.fetchObjectIDs(from, fetchClauses) } @@ -2353,16 +2352,16 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("testNumber", isEqualTo: 0), - OrderBy(.Descending("testEntityID")) + Where(#keyPath(TestEntity1.testNumber), isEqualTo: 0), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] - let objects = self.expectLogger([.LogWarning]) { + let objects = self.expectLogger([.logWarning]) { transaction.fetchAll(from, fetchClauses) } XCTAssertNil(objects) - let objectIDs = self.expectLogger([.LogWarning]) { + let objectIDs = self.expectLogger([.logWarning]) { transaction.fetchObjectIDs(from, fetchClauses) } @@ -2382,19 +2381,19 @@ final class FetchTests: BaseTestDataTestCase { stack.beginSynchronous { (transaction) in - let from = From(TestEntity1) + let from = From() do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) XCTAssertEqual(objects?.count, 3) XCTAssertEqual( - Set((objects ?? []).map { $0.testNumber!.integerValue }), + Set((objects ?? []).map { $0.testNumber!.intValue }), [4, 5] as Set ) // configuration is ambiguous @@ -2409,15 +2408,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) XCTAssertEqual(objects?.count, 3) XCTAssertEqual( - Set((objects ?? []).map { $0.testNumber!.integerValue }), + Set((objects ?? []).map { $0.testNumber!.intValue }), [1, 2] as Set ) // configuration is ambiguous @@ -2432,8 +2431,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -2450,8 +2449,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2475,8 +2474,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2500,8 +2499,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -2518,8 +2517,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2543,8 +2542,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2568,8 +2567,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -2586,15 +2585,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - OrderBy(.Ascending("testEntityID")) + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] - let objects = self.expectLogger([.LogWarning]) { + let objects = self.expectLogger([.logWarning]) { transaction.fetchAll(from, fetchClauses) } XCTAssertNil(objects) - let objectIDs = self.expectLogger([.LogWarning]) { + let objectIDs = self.expectLogger([.logWarning]) { transaction.fetchObjectIDs(from, fetchClauses) } @@ -2603,15 +2602,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - OrderBy(.Descending("testEntityID")) + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ] - let objects = self.expectLogger([.LogWarning]) { + let objects = self.expectLogger([.logWarning]) { transaction.fetchAll(from, fetchClauses) } XCTAssertNil(objects) - let objectIDs = self.expectLogger([.LogWarning]) { + let objectIDs = self.expectLogger([.logWarning]) { transaction.fetchObjectIDs(from, fetchClauses) } @@ -2635,15 +2634,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) XCTAssertEqual(objects?.count, 3) XCTAssertEqual( - Set((objects ?? []).map { $0.testNumber!.integerValue }), + Set((objects ?? []).map { $0.testNumber!.intValue }), [4, 5] as Set ) // configuration is ambiguous @@ -2658,15 +2657,15 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) XCTAssertEqual(objects?.count, 3) XCTAssertEqual( - Set((objects ?? []).map { $0.testNumber!.integerValue }), + Set((objects ?? []).map { $0.testNumber!.intValue }), [1, 2] as Set ) // configuration is ambiguous @@ -2681,8 +2680,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -2699,8 +2698,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2724,8 +2723,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2749,8 +2748,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -2767,8 +2766,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2792,8 +2791,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ] let objects = transaction.fetchAll(from, fetchClauses) @@ -2817,8 +2816,8 @@ final class FetchTests: BaseTestDataTestCase { do { let fetchClauses: [FetchClause] = [ - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] let objects = transaction.fetchAll(from, fetchClauses) XCTAssertNotNil(objects) @@ -2842,13 +2841,13 @@ final class FetchTests: BaseTestDataTestCase { stack.beginSynchronous { (transaction) in - let from = From(TestEntity1) + let from = From() do { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -2858,8 +2857,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K < %@", "testNumber", 5), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -2869,8 +2868,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -2883,8 +2882,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -2894,8 +2893,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K < %@", "testNumber", 5), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -2905,8 +2904,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -2917,24 +2916,24 @@ final class FetchTests: BaseTestDataTestCase { let from = From("Config1") do { - let count = self.expectLogger([.LogWarning]) { + let count = self.expectLogger([.logWarning]) { transaction.fetchCount( from, - Where("%K < %@", "testNumber", 4), - OrderBy(.Ascending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) } XCTAssertNil(count) } do { - let count = self.expectLogger([.LogWarning]) { + let count = self.expectLogger([.logWarning]) { transaction.fetchCount( from, - Where("testNumber", isEqualTo: 0), - OrderBy(.Descending("testEntityID")) + Where(#keyPath(TestEntity1.testNumber), isEqualTo: 0), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ) } XCTAssertNil(count) @@ -2953,13 +2952,13 @@ final class FetchTests: BaseTestDataTestCase { stack.beginSynchronous { (transaction) in - let from = From(TestEntity1) + let from = From() do { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -2969,8 +2968,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -2980,8 +2979,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -2994,8 +2993,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3005,8 +3004,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3016,8 +3015,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -3030,8 +3029,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3041,8 +3040,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3052,8 +3051,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -3064,24 +3063,24 @@ final class FetchTests: BaseTestDataTestCase { let from = From("Config2") do { - let count = self.expectLogger([.LogWarning]) { + let count = self.expectLogger([.logWarning]) { transaction.fetchCount( from, - Where("%K < %@", "testNumber", 4), - OrderBy(.Ascending("testEntityID")) + Where("%K < %@", #keyPath(TestEntity1.testNumber), 4), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) } XCTAssertNil(count) } do { - let count = self.expectLogger([.LogWarning]) { + let count = self.expectLogger([.logWarning]) { transaction.fetchCount( from, - Where("testNumber", isEqualTo: 0), - OrderBy(.Descending("testEntityID")) + Where(#keyPath(TestEntity1.testNumber), isEqualTo: 0), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))) ) } XCTAssertNil(count) @@ -3105,8 +3104,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3116,8 +3115,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3127,8 +3126,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -3141,8 +3140,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3152,8 +3151,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3163,8 +3162,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) @@ -3177,8 +3176,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")), + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3188,8 +3187,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K < %@", "testNumber", 3), - OrderBy(.Descending("testEntityID")), + Where("%K < %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.descending(#keyPath(TestEntity1.testEntityID))), Tweak { $0.fetchLimit = 3 } ) XCTAssertNotNil(count) @@ -3199,8 +3198,8 @@ final class FetchTests: BaseTestDataTestCase { let count = transaction.fetchCount( from, - Where("%K > %@", "testNumber", 5), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 5), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ) XCTAssertNotNil(count) XCTAssertEqual(count, 0) diff --git a/CoreStoreTests/FromTests.swift b/CoreStoreTests/FromTests.swift index 5c03671..6a0a740 100644 --- a/CoreStoreTests/FromTests.swift +++ b/CoreStoreTests/FromTests.swift @@ -90,7 +90,7 @@ final class FromTests: BaseTestCase { let from = From("Config1") let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } @@ -146,7 +146,7 @@ final class FromTests: BaseTestCase { let from = From("Config2") let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } @@ -164,7 +164,7 @@ final class FromTests: BaseTestCase { let from = From() let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } @@ -182,7 +182,7 @@ final class FromTests: BaseTestCase { let from = From("Config1") let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } @@ -200,7 +200,7 @@ final class FromTests: BaseTestCase { let from = From("Config2") let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } @@ -256,7 +256,7 @@ final class FromTests: BaseTestCase { let from = From("Config2") let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } @@ -289,7 +289,7 @@ final class FromTests: BaseTestCase { let from = From("Config1") let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } @@ -307,7 +307,7 @@ final class FromTests: BaseTestCase { let from = From("Config2") let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } @@ -363,7 +363,7 @@ final class FromTests: BaseTestCase { let from = From("Config2") let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } @@ -396,7 +396,7 @@ final class FromTests: BaseTestCase { let from = From("Config1") let request = CoreStoreFetchRequest() - let storesFound = self.expectLogger([.LogWarning]) { + let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } diff --git a/CoreStoreTests/GroupByTests.swift b/CoreStoreTests/GroupByTests.swift index 3bc8fd7..cf1e583 100644 --- a/CoreStoreTests/GroupByTests.swift +++ b/CoreStoreTests/GroupByTests.swift @@ -66,10 +66,10 @@ final class GroupByTests: BaseTestCase { self.prepareStack { (dataStack) in - let groupBy = GroupBy("testString") + let groupBy = GroupBy(#keyPath(TestEntity1.testString)) let request = CoreStoreFetchRequest() - _ = From(TestEntity1).applyToFetchRequest(request, context: dataStack.mainContext) + _ = From().applyToFetchRequest(request, context: dataStack.mainContext) groupBy.applyToFetchRequest(request) XCTAssertNotNil(request.propertiesToGroupBy) diff --git a/CoreStoreTests/ImportTests.swift b/CoreStoreTests/ImportTests.swift index 5190765..f48c1bf 100644 --- a/CoreStoreTests/ImportTests.swift +++ b/CoreStoreTests/ImportTests.swift @@ -43,19 +43,19 @@ class ImportTests: BaseTestDataTestCase { do { let object = try transaction.importObject( - Into(TestEntity1), + Into(), source: [ - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 1), - "testDecimal": NSDecimalNumber(string: "1"), - "testString": "nil:TestEntity1:1", - "testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!, + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 1), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "1"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:1", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!, "skip_insert": "" ] ) XCTAssertNil(object) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 0) + XCTAssertEqual(transaction.fetchCount(From()), 0) } catch { @@ -72,18 +72,18 @@ class ImportTests: BaseTestDataTestCase { stack.beginSynchronous { (transaction) in - let errorExpectation = self.expectationWithDescription("error") + let errorExpectation = self.expectation(description: "error") do { let _ = try transaction.importObject( - Into(TestEntity1), + Into(), source: [ - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 1), - "testDecimal": NSDecimalNumber(string: "1"), - "testString": "nil:TestEntity1:1", - "testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!, + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 1), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "1"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:1", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!, "throw_on_insert": "" ] ) @@ -92,9 +92,9 @@ class ImportTests: BaseTestDataTestCase { catch _ as TestInsertError { errorExpectation.fulfill() - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(transaction.fetchCount(From()), 1) - let object = transaction.fetchOne(From(TestEntity1)) + let object = transaction.fetchOne(From()) XCTAssertNotNil(object) XCTAssertNil(object?.testEntityID) XCTAssertNil(object?.testBoolean) @@ -124,45 +124,45 @@ class ImportTests: BaseTestDataTestCase { do { let object = try transaction.importObject( - Into(TestEntity1), + Into(), source: [ - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 1), - "testDecimal": NSDecimalNumber(string: "1"), - "testString": "nil:TestEntity1:1", - "testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")! + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 1), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "1"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:1", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-01T00:00:00Z")! ] ) XCTAssertNotNil(object) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(transaction.fetchCount(From()), 1) XCTAssertNil(object?.testEntityID) - XCTAssertEqual(object?.testBoolean, NSNumber(bool: true)) - XCTAssertEqual(object?.testNumber, NSNumber(integer: 1)) + XCTAssertEqual(object?.testBoolean, NSNumber(value: true)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 1)) XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "1")) XCTAssertEqual(object?.testString, "nil:TestEntity1:1") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!) + XCTAssertEqual(object?.testData, ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!) try transaction.importObject( object!, source: [ - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 2), - "testDecimal": NSDecimalNumber(string: "2"), - "testString": "nil:TestEntity1:2", - "testData": ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")! + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 2), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "2"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:2", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:2" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-02T00:00:00Z")! ] ) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(transaction.fetchCount(From()), 1) XCTAssertNil(object?.testEntityID) - XCTAssertEqual(object?.testBoolean, NSNumber(bool: false)) - XCTAssertEqual(object?.testNumber, NSNumber(integer: 2)) + XCTAssertEqual(object?.testBoolean, NSNumber(value: false)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 2)) XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "2")) XCTAssertEqual(object?.testString, "nil:TestEntity1:2") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")!) + XCTAssertEqual(object?.testData, ("nil:TestEntity1:2" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-02T00:00:00Z")!) } catch { @@ -184,39 +184,39 @@ class ImportTests: BaseTestDataTestCase { let sourceArray: [TestEntity1.ImportSource] = [ [ - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 1), - "testDecimal": NSDecimalNumber(string: "1"), - "testString": "nil:TestEntity1:1", - "testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!, + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 1), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "1"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:1", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!, "skip_insert": "" ], [ - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 2), - "testDecimal": NSDecimalNumber(string: "2"), - "testString": "nil:TestEntity1:2", - "testData": ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")! + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 2), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "2"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:2", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:2" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-02T00:00:00Z")! ] ] let objects = try transaction.importObjects( - Into(TestEntity1), + Into(), sourceArray: sourceArray ) XCTAssertEqual(objects.count, 1) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(transaction.fetchCount(From()), 1) let object = objects[0] let dictionary = sourceArray[1] XCTAssertNil(object.testEntityID) - XCTAssertEqual(object.testBoolean, dictionary["testBoolean"] as? NSNumber) - XCTAssertEqual(object.testNumber, dictionary["testNumber"] as? NSNumber) - XCTAssertEqual(object.testDecimal, dictionary["testDecimal"] as? NSDecimalNumber) - XCTAssertEqual(object.testString, dictionary["testString"] as? String) - XCTAssertEqual(object.testData, dictionary["testData"] as? NSData) - XCTAssertEqual(object.testDate, dictionary["testDate"] as? NSDate) + XCTAssertEqual(object.testBoolean, dictionary[(#keyPath(TestEntity1.testBoolean))] as? NSNumber) + XCTAssertEqual(object.testNumber, dictionary[(#keyPath(TestEntity1.testNumber))] as? NSNumber) + XCTAssertEqual(object.testDecimal, dictionary[(#keyPath(TestEntity1.testDecimal))] as? NSDecimalNumber) + XCTAssertEqual(object.testString, dictionary[(#keyPath(TestEntity1.testString))] as? String) + XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data) + XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date) } catch { @@ -234,30 +234,30 @@ class ImportTests: BaseTestDataTestCase { stack.beginSynchronous { (transaction) in - let errorExpectation = self.expectationWithDescription("error") + let errorExpectation = self.expectation(description: "error") do { let sourceArray: [TestEntity1.ImportSource] = [ [ - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 1), - "testDecimal": NSDecimalNumber(string: "1"), - "testString": "nil:TestEntity1:1", - "testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!, + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 1), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "1"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:1", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!, "throw_on_insert": "" ], [ - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 2), - "testDecimal": NSDecimalNumber(string: "2"), - "testString": "nil:TestEntity1:2", - "testData": ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")! + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 2), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "2"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:2", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:2" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-02T00:00:00Z")! ] ] let _ = try transaction.importObjects( - Into(TestEntity1), + Into(), sourceArray: sourceArray ) XCTFail() @@ -265,9 +265,9 @@ class ImportTests: BaseTestDataTestCase { catch _ as TestInsertError { errorExpectation.fulfill() - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(transaction.fetchCount(From()), 1) - let object = transaction.fetchOne(From(TestEntity1)) + let object = transaction.fetchOne(From()) XCTAssertNotNil(object) XCTAssertNil(object?.testEntityID) XCTAssertNil(object?.testBoolean) @@ -298,28 +298,28 @@ class ImportTests: BaseTestDataTestCase { let sourceArray: [TestEntity1.ImportSource] = [ [ - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 1), - "testDecimal": NSDecimalNumber(string: "1"), - "testString": "nil:TestEntity1:1", - "testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")! + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 1), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "1"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:1", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-01T00:00:00Z")! ], [ - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 2), - "testDecimal": NSDecimalNumber(string: "2"), - "testString": "nil:TestEntity1:2", - "testData": ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")! + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 2), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "2"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:2", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:2" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-02T00:00:00Z")! ] ] let objects = try transaction.importObjects( - Into(TestEntity1), + Into(), sourceArray: sourceArray ) XCTAssertEqual(objects.count, sourceArray.count) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 2) + XCTAssertEqual(transaction.fetchCount(From()), 2) for i in 0 ..< sourceArray.count { @@ -327,12 +327,12 @@ class ImportTests: BaseTestDataTestCase { let dictionary = sourceArray[i] XCTAssertNil(object.testEntityID) - XCTAssertEqual(object.testBoolean, dictionary["testBoolean"] as? NSNumber) - XCTAssertEqual(object.testNumber, dictionary["testNumber"] as? NSNumber) - XCTAssertEqual(object.testDecimal, dictionary["testDecimal"] as? NSDecimalNumber) - XCTAssertEqual(object.testString, dictionary["testString"] as? String) - XCTAssertEqual(object.testData, dictionary["testData"] as? NSData) - XCTAssertEqual(object.testDate, dictionary["testDate"] as? NSDate) + XCTAssertEqual(object.testBoolean, dictionary[(#keyPath(TestEntity1.testBoolean))] as? NSNumber) + XCTAssertEqual(object.testNumber, dictionary[(#keyPath(TestEntity1.testNumber))] as? NSNumber) + XCTAssertEqual(object.testDecimal, dictionary[(#keyPath(TestEntity1.testDecimal))] as? NSDecimalNumber) + XCTAssertEqual(object.testString, dictionary[(#keyPath(TestEntity1.testString))] as? String) + XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data) + XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date) } } catch { @@ -356,20 +356,20 @@ class ImportTests: BaseTestDataTestCase { do { let object = try transaction.importUniqueObject( - Into(TestEntity1), + Into(), source: [ - "testEntityID": NSNumber(integer: 106), - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!, + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!, "skip_insert": "" ] ) XCTAssertNil(object) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 5) + XCTAssertEqual(transaction.fetchCount(From()), 5) } catch { @@ -378,33 +378,33 @@ class ImportTests: BaseTestDataTestCase { do { let object = try transaction.importUniqueObject( - Into(TestEntity1), + Into(), source: [ - "testEntityID": NSNumber(integer: 105), - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!, + #keyPath(TestEntity1.testEntityID): NSNumber(value: 105), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!, "skip_update": "" ] ) XCTAssertNil(object) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 5) + XCTAssertEqual(transaction.fetchCount(From()), 5) - let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 105)) + let existingObjects = transaction.fetchAll(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105)) XCTAssertNotNil(existingObjects) XCTAssertEqual(existingObjects?.count, 1) let existingObject = existingObjects?[0] - XCTAssertEqual(existingObject?.testEntityID, NSNumber(integer: 105)) - XCTAssertEqual(existingObject?.testBoolean, NSNumber(bool: true)) - XCTAssertEqual(existingObject?.testNumber, NSNumber(integer: 5)) + XCTAssertEqual(existingObject?.testEntityID, NSNumber(value: 105)) + XCTAssertEqual(existingObject?.testBoolean, NSNumber(value: true)) + XCTAssertEqual(existingObject?.testNumber, NSNumber(value: 5)) XCTAssertEqual(existingObject?.testDecimal, NSDecimalNumber(string: "5")) XCTAssertEqual(existingObject?.testString, "nil:TestEntity1:5") - XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(existingObject?.testDate, self.dateFormatter.dateFromString("2000-01-05T00:00:00Z")!) + XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(existingObject?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!) } catch { @@ -414,6 +414,123 @@ class ImportTests: BaseTestDataTestCase { } } + @objc + dynamic func test_ThatImportUniqueObjects_ImportsLastOfImportSourcesWithSameIDs() { + + self.prepareStack { (stack) in + + self.prepareTestDataForStack(stack) + + stack.beginSynchronous { (transaction) in + + do { + + let sourceArray: [TestEntity1.ImportSource] = [ + [ + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")! + ], + [ + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 7), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "7"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:7", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-07T00:00:00Z")! + ] + ] + let objects = try transaction.importUniqueObjects( + Into(), + sourceArray: sourceArray + ) + + XCTAssertEqual(objects.count, 1) + XCTAssertEqual(transaction.fetchCount(From()), 6) + + let object = objects[0] + let dictionary = sourceArray[1] + XCTAssertEqual(object.testEntityID, dictionary[(#keyPath(TestEntity1.testEntityID))] as? NSNumber) + XCTAssertEqual(object.testBoolean, dictionary[(#keyPath(TestEntity1.testBoolean))] as? NSNumber) + XCTAssertEqual(object.testNumber, dictionary[(#keyPath(TestEntity1.testNumber))] as? NSNumber) + XCTAssertEqual(object.testDecimal, dictionary[(#keyPath(TestEntity1.testDecimal))] as? NSDecimalNumber) + XCTAssertEqual(object.testString, dictionary[(#keyPath(TestEntity1.testString))] as? String) + XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data) + XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date) + } + catch { + + XCTFail() + } + transaction.context.reset() + } + } + } + + @objc + dynamic func test_ThatImportUniqueObjects_MaintainsOrderOfInputSourceArray() { + + self.prepareStack { (stack) in + + self.prepareTestDataForStack(stack) + + stack.beginSynchronous { (transaction) in + + do { + + let sourceArray: [TestEntity1.ImportSource] = [ + [ + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")! + ], + [ + #keyPath(TestEntity1.testEntityID): NSNumber(value: 107), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 7), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "7"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:7", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-07T00:00:00Z")! + ] + ] + + let objects = try transaction.importUniqueObjects( + Into(), + sourceArray: sourceArray + ) + + XCTAssertEqual(objects.count, 2) + + zip(objects, sourceArray) + .forEach { object, dictionary in + XCTAssertEqual(object.testEntityID, dictionary[(#keyPath(TestEntity1.testEntityID))] as? NSNumber) + XCTAssertEqual(object.testBoolean, dictionary[(#keyPath(TestEntity1.testBoolean))] as? NSNumber) + XCTAssertEqual(object.testNumber, dictionary[(#keyPath(TestEntity1.testNumber))] as? NSNumber) + XCTAssertEqual(object.testDecimal, dictionary[(#keyPath(TestEntity1.testDecimal))] as? NSDecimalNumber) + XCTAssertEqual(object.testString, dictionary[(#keyPath(TestEntity1.testString))] as? String) + XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data) + XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date) + } + } + catch { + + XCTFail() + } + transaction.context.reset() + } + } + } + @objc dynamic func test_ThatImportUniqueObject_CanThrowError() { @@ -425,19 +542,19 @@ class ImportTests: BaseTestDataTestCase { do { - let errorExpectation = self.expectationWithDescription("error") + let errorExpectation = self.expectation(description: "error") do { let _ = try transaction.importUniqueObject( - Into(TestEntity1), + Into(), source: [ - "testEntityID": NSNumber(integer: 106), - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!, + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!, "throw_on_insert": "" ] ) @@ -446,11 +563,11 @@ class ImportTests: BaseTestDataTestCase { catch _ as TestInsertError { errorExpectation.fulfill() - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6) + XCTAssertEqual(transaction.fetchCount(From()), 6) - let object = transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 106)) + let object = transaction.fetchOne(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106)) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 106)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 106)) XCTAssertNil(object?.testBoolean) XCTAssertNil(object?.testNumber) XCTAssertNil(object?.testDecimal) @@ -466,19 +583,19 @@ class ImportTests: BaseTestDataTestCase { } do { - let errorExpectation = self.expectationWithDescription("error") + let errorExpectation = self.expectation(description: "error") do { let _ = try transaction.importUniqueObject( - Into(TestEntity1), + Into(), source: [ - "testEntityID": NSNumber(integer: 105), - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!, + #keyPath(TestEntity1.testEntityID): NSNumber(value: 105), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!, "throw_on_update": "" ] ) @@ -487,21 +604,21 @@ class ImportTests: BaseTestDataTestCase { catch _ as TestUpdateError { errorExpectation.fulfill() - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6) + XCTAssertEqual(transaction.fetchCount(From()), 6) - let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 105)) + let existingObjects = transaction.fetchAll(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105)) XCTAssertNotNil(existingObjects) XCTAssertEqual(existingObjects?.count, 1) let existingObject = existingObjects?[0] XCTAssertNotNil(existingObject) - XCTAssertEqual(existingObject?.testEntityID, NSNumber(integer: 105)) - XCTAssertEqual(existingObject?.testBoolean, NSNumber(bool: true)) - XCTAssertEqual(existingObject?.testNumber, NSNumber(integer: 5)) + XCTAssertEqual(existingObject?.testEntityID, NSNumber(value: 105)) + XCTAssertEqual(existingObject?.testBoolean, NSNumber(value: true)) + XCTAssertEqual(existingObject?.testNumber, NSNumber(value: 5)) XCTAssertEqual(existingObject?.testDecimal, NSDecimalNumber(string: "5")) XCTAssertEqual(existingObject?.testString, "nil:TestEntity1:5") - XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(existingObject?.testDate, self.dateFormatter.dateFromString("2000-01-05T00:00:00Z")!) + XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(existingObject?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!) } catch { @@ -526,27 +643,27 @@ class ImportTests: BaseTestDataTestCase { do { let object = try transaction.importUniqueObject( - Into(TestEntity1), + Into(), source: [ - "testEntityID": NSNumber(integer: 106), - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")! + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")! ] ) XCTAssertNotNil(object) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6) + XCTAssertEqual(transaction.fetchCount(From()), 6) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 106)) - XCTAssertEqual(object?.testBoolean, NSNumber(bool: true)) - XCTAssertEqual(object?.testNumber, NSNumber(integer: 6)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 106)) + XCTAssertEqual(object?.testBoolean, NSNumber(value: true)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 6)) XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "6")) XCTAssertEqual(object?.testString, "nil:TestEntity1:6") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!) + XCTAssertEqual(object?.testData, ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!) } catch { @@ -555,29 +672,29 @@ class ImportTests: BaseTestDataTestCase { do { let object = try transaction.importUniqueObject( - Into(TestEntity1), + Into(), source: [ - "testEntityID": NSNumber(integer: 106), - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 7), - "testDecimal": NSDecimalNumber(string: "7"), - "testString": "nil:TestEntity1:7", - "testData": ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")!, + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 7), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "7"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:7", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-07T00:00:00Z")!, ] ) XCTAssertNotNil(object) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6) + XCTAssertEqual(transaction.fetchCount(From()), 6) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 106)) - XCTAssertEqual(object?.testBoolean, NSNumber(bool: false)) - XCTAssertEqual(object?.testNumber, NSNumber(integer: 7)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 106)) + XCTAssertEqual(object?.testBoolean, NSNumber(value: false)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 7)) XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "7")) XCTAssertEqual(object?.testString, "nil:TestEntity1:7") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")!) + XCTAssertEqual(object?.testData, ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-07T00:00:00Z")!) - let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 106)) + let existingObjects = transaction.fetchAll(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106)) XCTAssertNotNil(existingObjects) XCTAssertEqual(existingObjects?.count, 1) @@ -606,41 +723,41 @@ class ImportTests: BaseTestDataTestCase { let sourceArray: [TestEntity1.ImportSource] = [ [ - "testEntityID": NSNumber(integer: 106), - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!, + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!, "skip_insert": "" ], [ - "testEntityID": NSNumber(integer: 107), - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 7), - "testDecimal": NSDecimalNumber(string: "7"), - "testString": "nil:TestEntity1:7", - "testData": ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")! + #keyPath(TestEntity1.testEntityID): NSNumber(value: 107), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 7), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "7"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:7", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-07T00:00:00Z")! ] ] let objects = try transaction.importUniqueObjects( - Into(TestEntity1), + Into(), sourceArray: sourceArray ) XCTAssertEqual(objects.count, 1) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6) + XCTAssertEqual(transaction.fetchCount(From()), 6) let object = objects[0] let dictionary = sourceArray[1] - XCTAssertEqual(object.testEntityID, dictionary["testEntityID"] as? NSNumber) - XCTAssertEqual(object.testBoolean, dictionary["testBoolean"] as? NSNumber) - XCTAssertEqual(object.testNumber, dictionary["testNumber"] as? NSNumber) - XCTAssertEqual(object.testDecimal, dictionary["testDecimal"] as? NSDecimalNumber) - XCTAssertEqual(object.testString, dictionary["testString"] as? String) - XCTAssertEqual(object.testData, dictionary["testData"] as? NSData) - XCTAssertEqual(object.testDate, dictionary["testDate"] as? NSDate) + XCTAssertEqual(object.testEntityID, dictionary[(#keyPath(TestEntity1.testEntityID))] as? NSNumber) + XCTAssertEqual(object.testBoolean, dictionary[(#keyPath(TestEntity1.testBoolean))] as? NSNumber) + XCTAssertEqual(object.testNumber, dictionary[(#keyPath(TestEntity1.testNumber))] as? NSNumber) + XCTAssertEqual(object.testDecimal, dictionary[(#keyPath(TestEntity1.testDecimal))] as? NSDecimalNumber) + XCTAssertEqual(object.testString, dictionary[(#keyPath(TestEntity1.testString))] as? String) + XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data) + XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date) } catch { @@ -660,32 +777,32 @@ class ImportTests: BaseTestDataTestCase { stack.beginSynchronous { (transaction) in - let errorExpectation = self.expectationWithDescription("error") + let errorExpectation = self.expectation(description: "error") do { let sourceArray: [TestEntity1.ImportSource] = [ [ - "testEntityID": NSNumber(integer: 106), - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!, + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!, "throw_on_id": "" ], [ - "testEntityID": NSNumber(integer: 107), - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 7), - "testDecimal": NSDecimalNumber(string: "7"), - "testString": "nil:TestEntity1:7", - "testData": ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")! + #keyPath(TestEntity1.testEntityID): NSNumber(value: 107), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 7), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "7"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:7", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-07T00:00:00Z")! ] ] let _ = try transaction.importUniqueObjects( - Into(TestEntity1), + Into(), sourceArray: sourceArray ) XCTFail() @@ -693,10 +810,10 @@ class ImportTests: BaseTestDataTestCase { catch _ as TestIDError { errorExpectation.fulfill() - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 5) + XCTAssertEqual(transaction.fetchCount(From()), 5) - XCTAssertNil(transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 106))) - XCTAssertNil(transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 107))) + XCTAssertNil(transaction.fetchOne(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106))) + XCTAssertNil(transaction.fetchOne(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 107))) } catch { @@ -707,32 +824,32 @@ class ImportTests: BaseTestDataTestCase { } stack.beginSynchronous { (transaction) in - let errorExpectation = self.expectationWithDescription("error") + let errorExpectation = self.expectation(description: "error") do { let sourceArray: [TestEntity1.ImportSource] = [ [ - "testEntityID": NSNumber(integer: 106), - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!, + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!, "throw_on_insert": "" ], [ - "testEntityID": NSNumber(integer: 107), - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 7), - "testDecimal": NSDecimalNumber(string: "7"), - "testString": "nil:TestEntity1:7", - "testData": ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")! + #keyPath(TestEntity1.testEntityID): NSNumber(value: 107), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 7), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "7"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:7", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:7" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-07T00:00:00Z")! ] ] let _ = try transaction.importUniqueObjects( - Into(TestEntity1), + Into(), sourceArray: sourceArray ) XCTFail() @@ -741,9 +858,9 @@ class ImportTests: BaseTestDataTestCase { errorExpectation.fulfill() - let object = transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 106)) + let object = transaction.fetchOne(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 106)) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 106)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 106)) XCTAssertNil(object?.testBoolean) XCTAssertNil(object?.testNumber) XCTAssertNil(object?.testDecimal) @@ -760,23 +877,23 @@ class ImportTests: BaseTestDataTestCase { } stack.beginSynchronous { (transaction) in - let errorExpectation = self.expectationWithDescription("error") + let errorExpectation = self.expectation(description: "error") do { let sourceArray: [TestEntity1.ImportSource] = [ [ - "testEntityID": NSNumber(integer: 105), - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!, + #keyPath(TestEntity1.testEntityID): NSNumber(value: 105), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")!, "throw_on_update": "" ] ] let _ = try transaction.importUniqueObjects( - Into(TestEntity1), + Into(), sourceArray: sourceArray ) XCTFail() @@ -784,19 +901,19 @@ class ImportTests: BaseTestDataTestCase { catch _ as TestUpdateError { errorExpectation.fulfill() - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 5) + XCTAssertEqual(transaction.fetchCount(From()), 5) - let object = transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 105)) + let object = transaction.fetchOne(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105)) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 105)) - XCTAssertEqual(object?.testBoolean, NSNumber(bool: true)) - XCTAssertEqual(object?.testNumber, NSNumber(integer: 5)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 105)) + XCTAssertEqual(object?.testBoolean, NSNumber(value: true)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 5)) XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "5")) XCTAssertEqual(object?.testString, "nil:TestEntity1:5") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:5" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-05T00:00:00Z")!) + XCTAssertEqual(object?.testData, ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")!) - let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 105)) + let existingObjects = transaction.fetchAll(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105)) XCTAssertNotNil(existingObjects) XCTAssertEqual(existingObjects?.count, 1) @@ -826,44 +943,44 @@ class ImportTests: BaseTestDataTestCase { let sourceArray: [TestEntity1.ImportSource] = [ [ - "testEntityID": NSNumber(integer: 105), - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 15), - "testDecimal": NSDecimalNumber(string: "15"), - "testString": "nil:TestEntity1:15", - "testData": ("nil:TestEntity1:15" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-15T00:00:00Z")! + #keyPath(TestEntity1.testEntityID): NSNumber(value: 105), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 15), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "15"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:15", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:15" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-15T00:00:00Z")! ], [ - "testEntityID": NSNumber(integer: 106), - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 6), - "testDecimal": NSDecimalNumber(string: "6"), - "testString": "nil:TestEntity1:6", - "testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")! + #keyPath(TestEntity1.testEntityID): NSNumber(value: 106), + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 6), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "6"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:6", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:6" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-06T00:00:00Z")! ] ] let objects = try transaction.importUniqueObjects( - Into(TestEntity1), + Into(), sourceArray: sourceArray ) XCTAssertEqual(objects.count, sourceArray.count) - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6) + XCTAssertEqual(transaction.fetchCount(From()), 6) for i in 0 ..< sourceArray.count { let object = objects[i] let dictionary = sourceArray[i] - XCTAssertEqual(object.testEntityID, dictionary["testEntityID"] as? NSNumber) - XCTAssertEqual(object.testBoolean, dictionary["testBoolean"] as? NSNumber) - XCTAssertEqual(object.testNumber, dictionary["testNumber"] as? NSNumber) - XCTAssertEqual(object.testDecimal, dictionary["testDecimal"] as? NSDecimalNumber) - XCTAssertEqual(object.testString, dictionary["testString"] as? String) - XCTAssertEqual(object.testData, dictionary["testData"] as? NSData) - XCTAssertEqual(object.testDate, dictionary["testDate"] as? NSDate) + XCTAssertEqual(object.testEntityID, dictionary[(#keyPath(TestEntity1.testEntityID))] as? NSNumber) + XCTAssertEqual(object.testBoolean, dictionary[(#keyPath(TestEntity1.testBoolean))] as? NSNumber) + XCTAssertEqual(object.testNumber, dictionary[(#keyPath(TestEntity1.testNumber))] as? NSNumber) + XCTAssertEqual(object.testDecimal, dictionary[(#keyPath(TestEntity1.testDecimal))] as? NSDecimalNumber) + XCTAssertEqual(object.testString, dictionary[(#keyPath(TestEntity1.testString))] as? String) + XCTAssertEqual(object.testData, dictionary[(#keyPath(TestEntity1.testData))] as? Data) + XCTAssertEqual(object.testDate, dictionary[(#keyPath(TestEntity1.testDate))] as? Date) } - let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 105)) + let existingObjects = transaction.fetchAll(From(), Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 105)) XCTAssertNotNil(existingObjects) XCTAssertEqual(existingObjects?.count, 1) @@ -883,17 +1000,17 @@ class ImportTests: BaseTestDataTestCase { // MARK: - TestInsertError -private struct TestInsertError: ErrorType {} +private struct TestInsertError: Error {} // MARK: - TestUpdateError -private struct TestUpdateError: ErrorType {} +private struct TestUpdateError: Error {} // MARK: - TestIDError -private struct TestIDError: ErrorType {} +private struct TestIDError: Error {} // MARK: - TestEntity1 @@ -902,25 +1019,25 @@ extension TestEntity1: ImportableUniqueObject { // MARK: ImportableObject - typealias ImportSource = [String: AnyObject] + typealias ImportSource = [String: Any] - static func shouldInsertFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) -> Bool { + static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool { return source["skip_insert"] == nil } - func didInsertFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) throws { + func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws { if let _ = source["throw_on_insert"] { throw TestInsertError() } - self.testBoolean = source["testBoolean"] as? NSNumber - self.testNumber = source["testNumber"] as? NSNumber - self.testDecimal = source["testDecimal"] as? NSDecimalNumber - self.testString = source["testString"] as? String - self.testData = source["testData"] as? NSData - self.testDate = source["testDate"] as? NSDate + self.testBoolean = source[(#keyPath(TestEntity1.testBoolean))] as? NSNumber + self.testNumber = source[(#keyPath(TestEntity1.testNumber))] as? NSNumber + self.testDecimal = source[(#keyPath(TestEntity1.testDecimal))] as? NSDecimalNumber + self.testString = source[(#keyPath(TestEntity1.testString))] as? String + self.testData = source[(#keyPath(TestEntity1.testData))] as? Data + self.testDate = source[(#keyPath(TestEntity1.testDate))] as? Date self.testNil = nil } @@ -931,7 +1048,7 @@ extension TestEntity1: ImportableUniqueObject { static var uniqueIDKeyPath: String { - return "testEntityID" + return #keyPath(TestEntity1.testEntityID) } var uniqueIDValue: NSNumber { @@ -951,32 +1068,32 @@ extension TestEntity1: ImportableUniqueObject { } } - static func shouldUpdateFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) -> Bool { + static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool { return source["skip_update"] == nil } - static func uniqueIDFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) throws -> NSNumber? { + static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> NSNumber? { if let _ = source["throw_on_id"] { throw TestIDError() } - return source["testEntityID"] as? NSNumber + return source[(#keyPath(TestEntity1.testEntityID))] as? NSNumber } - func updateFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) throws { + func update(from source: ImportSource, in transaction: BaseDataTransaction) throws { if let _ = source["throw_on_update"] { throw TestUpdateError() } - self.testBoolean = source["testBoolean"] as? NSNumber - self.testNumber = source["testNumber"] as? NSNumber - self.testDecimal = source["testDecimal"] as? NSDecimalNumber - self.testString = source["testString"] as? String - self.testData = source["testData"] as? NSData - self.testDate = source["testDate"] as? NSDate + self.testBoolean = source[(#keyPath(TestEntity1.testBoolean))] as? NSNumber + self.testNumber = source[(#keyPath(TestEntity1.testNumber))] as? NSNumber + self.testDecimal = source[(#keyPath(TestEntity1.testDecimal))] as? NSDecimalNumber + self.testString = source[(#keyPath(TestEntity1.testString))] as? String + self.testData = source[(#keyPath(TestEntity1.testData))] as? Data + self.testDate = source[(#keyPath(TestEntity1.testDate))] as? Date self.testNil = nil } } diff --git a/CoreStoreTests/IntoTests.swift b/CoreStoreTests/IntoTests.swift index ffa7481..d101476 100644 --- a/CoreStoreTests/IntoTests.swift +++ b/CoreStoreTests/IntoTests.swift @@ -58,7 +58,7 @@ final class IntoTests: XCTestCase { } do { - let into = Into(TestEntity1) + let into = Into() XCTAssert(into.entityClass === TestEntity1.self) XCTAssertNil(into.configuration) XCTAssertTrue(into.inferStoreIfPossible) @@ -108,14 +108,14 @@ final class IntoTests: XCTestCase { do { let into = Into() - XCTAssertEqual(into, Into(TestEntity1)) + XCTAssertEqual(into, Into()) XCTAssertEqual(into, Into(TestEntity1.self as AnyClass)) XCTAssertFalse(into == Into()) XCTAssertNotEqual(into, Into("Config1")) } do { - let into = Into(TestEntity1) + let into = Into() XCTAssertEqual(into, Into()) XCTAssertEqual(into, Into(TestEntity1.self as AnyClass)) XCTAssertFalse(into == Into()) @@ -125,7 +125,7 @@ final class IntoTests: XCTestCase { let into = Into(TestEntity1.self as AnyClass) XCTAssert(into == Into()) - XCTAssertEqual(into, Into(TestEntity1)) + XCTAssertEqual(into, Into(TestEntity1.self)) XCTAssertFalse(into == Into()) XCTAssertFalse(into == Into("Config1")) } diff --git a/CoreStoreTests/ListObserverTests.swift b/CoreStoreTests/ListObserverTests.swift index b5fdb08..987d4de 100644 --- a/CoreStoreTests/ListObserverTests.swift +++ b/CoreStoreTests/ListObserverTests.swift @@ -42,9 +42,9 @@ class ListObserverTests: BaseTestDataTestCase { let observer = TestListObserver() let monitor = stack.monitorSectionedList( - From(TestEntity1), - SectionBy("testBoolean"), - OrderBy(.Ascending("testBoolean"), .Ascending("testEntityID")) + From(), + SectionBy(#keyPath(TestEntity1.testBoolean)), + OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID))) ) monitor.addObserver(observer) @@ -54,13 +54,13 @@ class ListObserverTests: BaseTestDataTestCase { var events = 0 - let willChangeExpectation = self.expectationForNotification( - "listMonitorWillChange:", + let willChangeExpectation = self.expectation( + forNotification: "listMonitorWillChange:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 0) - XCTAssertEqual((note.userInfo ?? [:]), NSDictionary()) + XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary()) defer { events += 1 @@ -68,14 +68,14 @@ class ListObserverTests: BaseTestDataTestCase { return events == 0 } ) - let didInsertSectionExpectation = self.expectationForNotification( - "listMonitor:didInsertSection:toSectionIndex:", + let didInsertSectionExpectation = self.expectation( + forNotification: "listMonitor:didInsertSection:toSectionIndex:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 1) XCTAssertEqual( - (note.userInfo ?? [:]), + ((note.userInfo as NSDictionary?) ?? [:]), [ "sectionInfo": monitor.sectionInfoAtIndex(0), "sectionIndex": 0 @@ -88,8 +88,8 @@ class ListObserverTests: BaseTestDataTestCase { return events == 1 } ) - let didInsertObjectExpectation = self.expectationForNotification( - "listMonitor:didInsertObject:toIndexPath:", + let didInsertObjectExpectation = self.expectation( + forNotification: "listMonitor:didInsertObject:toIndexPath:", object: observer, handler: { (note) -> Bool in @@ -98,7 +98,7 @@ class ListObserverTests: BaseTestDataTestCase { let userInfo = note.userInfo XCTAssertNotNil(userInfo) XCTAssertEqual( - Set(((userInfo as? [String: AnyObject]) ?? [:]).keys), + Set(userInfo?.keys.map({ $0 as! String }) ?? []), ["indexPath", "object"] ) @@ -107,12 +107,12 @@ class ListObserverTests: BaseTestDataTestCase { XCTAssertEqual(indexPath?.row, 0) let object = userInfo?["object"] as? TestEntity1 - XCTAssertEqual(object?.testBoolean, NSNumber(bool: true)) - XCTAssertEqual(object?.testNumber, NSNumber(integer: 1)) + XCTAssertEqual(object?.testBoolean, NSNumber(value: true)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 1)) XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "1")) XCTAssertEqual(object?.testString, "nil:TestEntity1:1") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!) + XCTAssertEqual(object?.testData, ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!) defer { events += 1 @@ -120,12 +120,12 @@ class ListObserverTests: BaseTestDataTestCase { return events == 2 } ) - let didChangeExpectation = self.expectationForNotification( - "listMonitorDidChange:", + let didChangeExpectation = self.expectation( + forNotification: "listMonitorDidChange:", object: observer, handler: { (note) -> Bool in - XCTAssertEqual((note.userInfo ?? [:]), NSDictionary()) + XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary()) defer { events += 1 @@ -133,26 +133,26 @@ class ListObserverTests: BaseTestDataTestCase { return events == 3 } ) - let saveExpectation = self.expectationWithDescription("save") + let saveExpectation = self.expectation(description: "save") stack.beginAsynchronous { (transaction) in - let object = transaction.create(Into(TestEntity1)) - object.testBoolean = NSNumber(bool: true) - object.testNumber = NSNumber(integer: 1) + let object = transaction.create(Into()) + object.testBoolean = NSNumber(value: true) + object.testNumber = NSNumber(value: 1) object.testDecimal = NSDecimalNumber(string: "1") object.testString = "nil:TestEntity1:1" - object.testData = ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)! - object.testDate = self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")! + object.testData = ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)! + object.testDate = self.dateFormatter.date(from: "2000-01-01T00:00:00Z")! transaction.commit { (result) in switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) saveExpectation.fulfill() - case .Failure: + case .failure: XCTFail() } } @@ -170,9 +170,9 @@ class ListObserverTests: BaseTestDataTestCase { let observer = TestListObserver() let monitor = stack.monitorSectionedList( - From(TestEntity1), - SectionBy("testBoolean"), - OrderBy(.Ascending("testBoolean"), .Ascending("testEntityID")) + From(), + SectionBy(#keyPath(TestEntity1.testBoolean)), + OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID))) ) monitor.addObserver(observer) @@ -185,13 +185,13 @@ class ListObserverTests: BaseTestDataTestCase { var events = 0 - let willChangeExpectation = self.expectationForNotification( - "listMonitorWillChange:", + let willChangeExpectation = self.expectation( + forNotification: "listMonitorWillChange:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 0) - XCTAssertEqual((note.userInfo ?? [:]), NSDictionary()) + XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary()) defer { events += 1 @@ -201,8 +201,8 @@ class ListObserverTests: BaseTestDataTestCase { ) for _ in 1 ... 2 { - let didUpdateObjectExpectation = self.expectationForNotification( - "listMonitor:didUpdateObject:atIndexPath:", + let didUpdateObjectExpectation = self.expectation( + forNotification: "listMonitor:didUpdateObject:atIndexPath:", object: observer, handler: { (note) -> Bool in @@ -211,7 +211,7 @@ class ListObserverTests: BaseTestDataTestCase { let userInfo = note.userInfo XCTAssertNotNil(userInfo) XCTAssertEqual( - Set(((userInfo as? [String: AnyObject]) ?? [:]).keys), + Set(userInfo?.keys.map({ $0 as! String }) ?? []), ["indexPath", "object"] ) @@ -220,27 +220,27 @@ class ListObserverTests: BaseTestDataTestCase { switch object?.testEntityID { - case NSNumber(integer: 101)?: + case NSNumber(value: 101)?: XCTAssertEqual(indexPath?.section, 1) XCTAssertEqual(indexPath?.row, 0) - XCTAssertEqual(object?.testBoolean, NSNumber(bool: true)) - XCTAssertEqual(object?.testNumber, NSNumber(integer: 11)) + XCTAssertEqual(object?.testBoolean, NSNumber(value: true)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 11)) XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "11")) XCTAssertEqual(object?.testString, "nil:TestEntity1:11") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-11T00:00:00Z")!) + XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!) - case NSNumber(integer: 102)?: + case NSNumber(value: 102)?: XCTAssertEqual(indexPath?.section, 0) XCTAssertEqual(indexPath?.row, 0) - XCTAssertEqual(object?.testBoolean, NSNumber(bool: false)) - XCTAssertEqual(object?.testNumber, NSNumber(integer: 22)) + XCTAssertEqual(object?.testBoolean, NSNumber(value: false)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 22)) XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "22")) XCTAssertEqual(object?.testString, "nil:TestEntity1:22") - XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!) - XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-22T00:00:00Z")!) + XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!) + XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!) default: XCTFail() @@ -253,13 +253,13 @@ class ListObserverTests: BaseTestDataTestCase { } ) } - let didChangeExpectation = self.expectationForNotification( - "listMonitorDidChange:", + let didChangeExpectation = self.expectation( + forNotification: "listMonitorDidChange:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 3) - XCTAssertEqual((note.userInfo ?? [:]), NSDictionary()) + XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary()) defer { events += 1 @@ -267,32 +267,32 @@ class ListObserverTests: BaseTestDataTestCase { return events == 3 } ) - let saveExpectation = self.expectationWithDescription("save") + let saveExpectation = self.expectation(description: "save") stack.beginAsynchronous { (transaction) in if let object = transaction.fetchOne( - From(TestEntity1), - Where("testEntityID", isEqualTo: 101)) { + From(), + Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) { - object.testNumber = NSNumber(integer: 11) + object.testNumber = NSNumber(value: 11) object.testDecimal = NSDecimalNumber(string: "11") object.testString = "nil:TestEntity1:11" - object.testData = ("nil:TestEntity1:11" as NSString).dataUsingEncoding(NSUTF8StringEncoding)! - object.testDate = self.dateFormatter.dateFromString("2000-01-11T00:00:00Z")! + object.testData = ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)! + object.testDate = self.dateFormatter.date(from: "2000-01-11T00:00:00Z")! } else { XCTFail() } if let object = transaction.fetchOne( - From(TestEntity1), - Where("testEntityID", isEqualTo: 102)) { + From(), + Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) { - object.testNumber = NSNumber(integer: 22) + object.testNumber = NSNumber(value: 22) object.testDecimal = NSDecimalNumber(string: "22") object.testString = "nil:TestEntity1:22" - object.testData = ("nil:TestEntity1:22" as NSString).dataUsingEncoding(NSUTF8StringEncoding)! - object.testDate = self.dateFormatter.dateFromString("2000-01-22T00:00:00Z")! + object.testData = ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)! + object.testDate = self.dateFormatter.date(from: "2000-01-22T00:00:00Z")! } else { @@ -302,11 +302,11 @@ class ListObserverTests: BaseTestDataTestCase { switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) saveExpectation.fulfill() - case .Failure: + case .failure: XCTFail() } } @@ -324,21 +324,21 @@ class ListObserverTests: BaseTestDataTestCase { let observer = TestListObserver() let monitor = stack.monitorSectionedList( - From(TestEntity1), - SectionBy("testBoolean"), - OrderBy(.Ascending("testBoolean"), .Ascending("testEntityID")) + From(), + SectionBy(#keyPath(TestEntity1.testBoolean)), + OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID))) ) monitor.addObserver(observer) var events = 0 - let willChangeExpectation = self.expectationForNotification( - "listMonitorWillChange:", + let willChangeExpectation = self.expectation( + forNotification: "listMonitorWillChange:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 0) - XCTAssertEqual((note.userInfo ?? [:]), NSDictionary()) + XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary()) defer { events += 1 @@ -346,8 +346,8 @@ class ListObserverTests: BaseTestDataTestCase { return events == 0 } ) - let didMoveObjectExpectation = self.expectationForNotification( - "listMonitor:didMoveObject:fromIndexPath:toIndexPath:", + let didMoveObjectExpectation = self.expectation( + forNotification: "listMonitor:didMoveObject:fromIndexPath:toIndexPath:", object: observer, handler: { (note) -> Bool in @@ -356,7 +356,7 @@ class ListObserverTests: BaseTestDataTestCase { let userInfo = note.userInfo XCTAssertNotNil(userInfo) XCTAssertEqual( - Set(((userInfo as? [String: AnyObject]) ?? [:]).keys), + Set(userInfo?.keys.map({ $0 as! String }) ?? []), ["fromIndexPath", "toIndexPath", "object"] ) @@ -369,8 +369,8 @@ class ListObserverTests: BaseTestDataTestCase { XCTAssertEqual(toIndexPath?.row, 1) let object = userInfo?["object"] as? TestEntity1 - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 102)) - XCTAssertEqual(object?.testBoolean, NSNumber(bool: true)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 102)) + XCTAssertEqual(object?.testBoolean, NSNumber(value: true)) defer { @@ -379,13 +379,13 @@ class ListObserverTests: BaseTestDataTestCase { return events == 1 } ) - let didChangeExpectation = self.expectationForNotification( - "listMonitorDidChange:", + let didChangeExpectation = self.expectation( + forNotification: "listMonitorDidChange:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 2) - XCTAssertEqual((note.userInfo ?? [:]), NSDictionary()) + XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary()) defer { events += 1 @@ -393,14 +393,14 @@ class ListObserverTests: BaseTestDataTestCase { return events == 2 } ) - let saveExpectation = self.expectationWithDescription("save") + let saveExpectation = self.expectation(description: "save") stack.beginAsynchronous { (transaction) in if let object = transaction.fetchOne( - From(TestEntity1), - Where("testEntityID", isEqualTo: 102)) { + From(), + Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 102)) { - object.testBoolean = NSNumber(bool: true) + object.testBoolean = NSNumber(value: true) } else { @@ -410,11 +410,11 @@ class ListObserverTests: BaseTestDataTestCase { switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) saveExpectation.fulfill() - case .Failure: + case .failure: XCTFail() } } @@ -432,21 +432,21 @@ class ListObserverTests: BaseTestDataTestCase { let observer = TestListObserver() let monitor = stack.monitorSectionedList( - From(TestEntity1), - SectionBy("testBoolean"), - OrderBy(.Ascending("testBoolean"), .Ascending("testEntityID")) + From(), + SectionBy(#keyPath(TestEntity1.testBoolean)), + OrderBy(.ascending(#keyPath(TestEntity1.testBoolean)), .ascending(#keyPath(TestEntity1.testEntityID))) ) monitor.addObserver(observer) var events = 0 - let willChangeExpectation = self.expectationForNotification( - "listMonitorWillChange:", + let willChangeExpectation = self.expectation( + forNotification: "listMonitorWillChange:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 0) - XCTAssertEqual((note.userInfo ?? [:]), NSDictionary()) + XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary()) defer { events += 1 @@ -456,8 +456,8 @@ class ListObserverTests: BaseTestDataTestCase { ) for _ in 1 ... 2 { - let didUpdateObjectExpectation = self.expectationForNotification( - "listMonitor:didDeleteObject:fromIndexPath:", + let didUpdateObjectExpectation = self.expectation( + forNotification: "listMonitor:didDeleteObject:fromIndexPath:", object: observer, handler: { (note) -> Bool in @@ -466,7 +466,7 @@ class ListObserverTests: BaseTestDataTestCase { let userInfo = note.userInfo XCTAssertNotNil(userInfo) XCTAssertEqual( - Set(((userInfo as? [String: AnyObject]) ?? [:]).keys), + Set(userInfo?.keys.map({ $0 as! String }) ?? []), ["indexPath", "object"] ) @@ -476,7 +476,7 @@ class ListObserverTests: BaseTestDataTestCase { XCTAssert(indexPath?.row == 0 || indexPath?.row == 1) let object = userInfo?["object"] as? TestEntity1 - XCTAssertEqual(object?.deleted, true) + XCTAssertEqual(object?.isDeleted, true) defer { @@ -486,8 +486,8 @@ class ListObserverTests: BaseTestDataTestCase { } ) } - let didDeleteSectionExpectation = self.expectationForNotification( - "listMonitor:didDeleteSection:fromSectionIndex:", + let didDeleteSectionExpectation = self.expectation( + forNotification: "listMonitor:didDeleteSection:fromSectionIndex:", object: observer, handler: { (note) -> Bool in @@ -496,16 +496,16 @@ class ListObserverTests: BaseTestDataTestCase { let userInfo = note.userInfo XCTAssertNotNil(userInfo) XCTAssertEqual( - Set(((userInfo as? [String: AnyObject]) ?? [:]).keys), + Set(userInfo?.keys.map({ $0 as! String }) ?? []), ["sectionInfo", "sectionIndex"] ) - let sectionInfo = userInfo?["sectionInfo"] + let sectionInfo = userInfo?["sectionInfo"] as? NSFetchedResultsSectionInfo XCTAssertNotNil(sectionInfo) XCTAssertEqual(sectionInfo?.name, "0") let sectionIndex = userInfo?["sectionIndex"] - XCTAssertEqual(sectionIndex as? NSNumber, NSNumber(integer: 0)) + XCTAssertEqual(sectionIndex as? NSNumber, NSNumber(value: 0)) defer { @@ -514,13 +514,13 @@ class ListObserverTests: BaseTestDataTestCase { return events == 3 } ) - let didChangeExpectation = self.expectationForNotification( - "listMonitorDidChange:", + let didChangeExpectation = self.expectation( + forNotification: "listMonitorDidChange:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 4) - XCTAssertEqual((note.userInfo ?? [:]), NSDictionary()) + XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary()) defer { events += 1 @@ -528,22 +528,22 @@ class ListObserverTests: BaseTestDataTestCase { return events == 4 } ) - let saveExpectation = self.expectationWithDescription("save") + let saveExpectation = self.expectation(description: "save") stack.beginAsynchronous { (transaction) in transaction.deleteAll( - From(TestEntity1), - Where("testBoolean", isEqualTo: false) + From(), + Where(#keyPath(TestEntity1.testBoolean), isEqualTo: false) ) transaction.commit { (result) in switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) saveExpectation.fulfill() - case .Failure: + case .failure: XCTFail() } } @@ -562,37 +562,37 @@ class TestListObserver: ListSectionObserver { typealias ListEntityType = TestEntity1 - func listMonitorWillChange(monitor: ListMonitor) { + func listMonitorWillChange(_ monitor: ListMonitor) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitorWillChange:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitorWillChange:"), object: self, userInfo: [:] ) } - func listMonitorDidChange(monitor: ListMonitor) { + func listMonitorDidChange(_ monitor: ListMonitor) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitorDidChange:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitorDidChange:"), object: self, userInfo: [:] ) } - func listMonitorWillRefetch(monitor: ListMonitor) { + func listMonitorWillRefetch(_ monitor: ListMonitor) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitorWillRefetch:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitorWillRefetch:"), object: self, userInfo: [:] ) } - func listMonitorDidRefetch(monitor: ListMonitor) { + func listMonitorDidRefetch(_ monitor: ListMonitor) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitorDidRefetch:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitorDidRefetch:"), object: self, userInfo: [:] ) @@ -601,10 +601,10 @@ class TestListObserver: ListSectionObserver { // MARK: ListObjectObserver - func listMonitor(monitor: ListMonitor, didInsertObject object: TestEntity1, toIndexPath indexPath: NSIndexPath) { + func listMonitor(_ monitor: ListMonitor, didInsertObject object: TestEntity1, toIndexPath indexPath: IndexPath) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitor:didInsertObject:toIndexPath:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitor:didInsertObject:toIndexPath:"), object: self, userInfo: [ "object": object, @@ -613,10 +613,10 @@ class TestListObserver: ListSectionObserver { ) } - func listMonitor(monitor: ListMonitor, didDeleteObject object: TestEntity1, fromIndexPath indexPath: NSIndexPath) { + func listMonitor(_ monitor: ListMonitor, didDeleteObject object: TestEntity1, fromIndexPath indexPath: IndexPath) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitor:didDeleteObject:fromIndexPath:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitor:didDeleteObject:fromIndexPath:"), object: self, userInfo: [ "object": object, @@ -625,10 +625,10 @@ class TestListObserver: ListSectionObserver { ) } - func listMonitor(monitor: ListMonitor, didUpdateObject object: TestEntity1, atIndexPath indexPath: NSIndexPath) { + func listMonitor(_ monitor: ListMonitor, didUpdateObject object: TestEntity1, atIndexPath indexPath: IndexPath) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitor:didUpdateObject:atIndexPath:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitor:didUpdateObject:atIndexPath:"), object: self, userInfo: [ "object": object, @@ -638,10 +638,10 @@ class TestListObserver: ListSectionObserver { } - func listMonitor(monitor: ListMonitor, didMoveObject object: TestEntity1, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { + func listMonitor(_ monitor: ListMonitor, didMoveObject object: TestEntity1, fromIndexPath: IndexPath, toIndexPath: IndexPath) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitor:didMoveObject:fromIndexPath:toIndexPath:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitor:didMoveObject:fromIndexPath:toIndexPath:"), object: self, userInfo: [ "object": object, @@ -654,10 +654,10 @@ class TestListObserver: ListSectionObserver { // MARK: ListSectionObserver - func listMonitor(monitor: ListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { + func listMonitor(_ monitor: ListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitor:didInsertSection:toSectionIndex:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitor:didInsertSection:toSectionIndex:"), object: self, userInfo: [ "sectionInfo": sectionInfo, @@ -666,10 +666,10 @@ class TestListObserver: ListSectionObserver { ) } - func listMonitor(monitor: ListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { + func listMonitor(_ monitor: ListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { - NSNotificationCenter.defaultCenter().postNotificationName( - "listMonitor:didDeleteSection:fromSectionIndex:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "listMonitor:didDeleteSection:fromSectionIndex:"), object: self, userInfo: [ "sectionInfo": sectionInfo, diff --git a/CoreStoreTests/ObjectObserverTests.swift b/CoreStoreTests/ObjectObserverTests.swift index cbcdd81..7884462 100644 --- a/CoreStoreTests/ObjectObserverTests.swift +++ b/CoreStoreTests/ObjectObserverTests.swift @@ -43,8 +43,8 @@ class ObjectObserverTests: BaseTestDataTestCase { self.prepareTestDataForStack(stack) guard let object = stack.fetchOne( - From(TestEntity1), - Where("testEntityID", isEqualTo: 101)) else { + From(), + Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else { XCTFail() return @@ -58,14 +58,14 @@ class ObjectObserverTests: BaseTestDataTestCase { var events = 0 - let willUpdateExpectation = self.expectationForNotification( - "objectMonitor:willUpdateObject:", + let willUpdateExpectation = self.expectation( + forNotification: "objectMonitor:willUpdateObject:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 0) XCTAssertEqual( - (note.userInfo ?? [:]), + ((note.userInfo as NSDictionary?) ?? [:]), ["object": object] as NSDictionary ) defer { @@ -75,26 +75,26 @@ class ObjectObserverTests: BaseTestDataTestCase { return events == 0 } ) - let didUpdateExpectation = self.expectationForNotification( - "objectMonitor:didUpdateObject:changedPersistentKeys:", + let didUpdateExpectation = self.expectation( + forNotification: "objectMonitor:didUpdateObject:changedPersistentKeys:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 1) XCTAssertEqual( - (note.userInfo ?? [:]), + ((note.userInfo as NSDictionary?) ?? [:]), [ "object": object, "changedPersistentKeys": Set( [ - "testNumber", - "testString" + #keyPath(TestEntity1.testNumber), + #keyPath(TestEntity1.testString) ] ) ] as NSDictionary ) let object = note.userInfo?["object"] as? TestEntity1 - XCTAssertEqual(object?.testNumber, NSNumber(integer: 10)) + XCTAssertEqual(object?.testNumber, NSNumber(value: 10)) XCTAssertEqual(object?.testString, "nil:TestEntity1:10") defer { @@ -104,7 +104,7 @@ class ObjectObserverTests: BaseTestDataTestCase { return events == 1 } ) - let saveExpectation = self.expectationWithDescription("save") + let saveExpectation = self.expectation(description: "save") stack.beginAsynchronous { (transaction) in guard let object = transaction.edit(object) else { @@ -112,18 +112,18 @@ class ObjectObserverTests: BaseTestDataTestCase { XCTFail() return } - object.testNumber = NSNumber(integer: 10) + object.testNumber = NSNumber(value: 10) object.testString = "nil:TestEntity1:10" transaction.commit { (result) in switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) saveExpectation.fulfill() - case .Failure: + case .failure: XCTFail() } } @@ -140,8 +140,8 @@ class ObjectObserverTests: BaseTestDataTestCase { self.prepareTestDataForStack(stack) guard let object = stack.fetchOne( - From(TestEntity1), - Where("testEntityID", isEqualTo: 101)) else { + From(), + Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101)) else { XCTFail() return @@ -155,14 +155,14 @@ class ObjectObserverTests: BaseTestDataTestCase { var events = 0 - let didDeleteExpectation = self.expectationForNotification( - "objectMonitor:didDeleteObject:", + let didDeleteExpectation = self.expectation( + forNotification: "objectMonitor:didDeleteObject:", object: observer, handler: { (note) -> Bool in XCTAssertEqual(events, 0) XCTAssertEqual( - (note.userInfo ?? [:]), + ((note.userInfo as NSDictionary?) ?? [:]), ["object": object] as NSDictionary ) defer { @@ -172,7 +172,7 @@ class ObjectObserverTests: BaseTestDataTestCase { return events == 0 } ) - let saveExpectation = self.expectationWithDescription("save") + let saveExpectation = self.expectation(description: "save") stack.beginAsynchronous { (transaction) in guard let object = transaction.edit(object) else { @@ -186,12 +186,12 @@ class ObjectObserverTests: BaseTestDataTestCase { switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) XCTAssertTrue(monitor.isObjectDeleted) saveExpectation.fulfill() - case .Failure: + case .failure: XCTFail() } } @@ -208,10 +208,10 @@ class TestObjectObserver: ObjectObserver { typealias ObjectEntityType = TestEntity1 - func objectMonitor(monitor: ObjectMonitor, willUpdateObject object: TestEntity1) { + func objectMonitor(_ monitor: ObjectMonitor, willUpdateObject object: TestEntity1) { - NSNotificationCenter.defaultCenter().postNotificationName( - "objectMonitor:willUpdateObject:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "objectMonitor:willUpdateObject:"), object: self, userInfo: [ "object": object @@ -219,10 +219,10 @@ class TestObjectObserver: ObjectObserver { ) } - func objectMonitor(monitor: ObjectMonitor, didUpdateObject object: TestEntity1, changedPersistentKeys: Set) { + func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: TestEntity1, changedPersistentKeys: Set) { - NSNotificationCenter.defaultCenter().postNotificationName( - "objectMonitor:didUpdateObject:changedPersistentKeys:", + NotificationCenter.default.post( + name: NSNotification.Name(rawValue: "objectMonitor:didUpdateObject:changedPersistentKeys:"), object: self, userInfo: [ "object": object, @@ -231,10 +231,10 @@ class TestObjectObserver: ObjectObserver { ) } - func objectMonitor(monitor: ObjectMonitor, didDeleteObject object: TestEntity1) { + func objectMonitor(_ monitor: ObjectMonitor, didDeleteObject object: TestEntity1) { - NSNotificationCenter.defaultCenter().postNotificationName( - "objectMonitor:didDeleteObject:", + NotificationCenter.default.post( + name: Notification.Name(rawValue: "objectMonitor:didDeleteObject:"), object: self, userInfo: [ "object": object diff --git a/CoreStoreTests/OrderByTests.swift b/CoreStoreTests/OrderByTests.swift index 2eea837..69af761 100644 --- a/CoreStoreTests/OrderByTests.swift +++ b/CoreStoreTests/OrderByTests.swift @@ -39,7 +39,7 @@ final class OrderByTests: XCTestCase { do { let orderBy = OrderBy() - XCTAssertEqual(orderBy, OrderBy([] as [NSSortDescriptor])) + XCTAssertEqual(orderBy, OrderBy([NSSortDescriptor]())) XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key", ascending: false))) XCTAssertTrue(orderBy.sortDescriptors.isEmpty) } @@ -48,9 +48,9 @@ final class OrderByTests: XCTestCase { let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true) let orderBy = OrderBy(sortDescriptor) XCTAssertEqual(orderBy, OrderBy(sortDescriptor)) - XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"))) - XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key2"))) - XCTAssertNotEqual(orderBy, OrderBy(.Descending("key1"))) + XCTAssertEqual(orderBy, OrderBy(.ascending("key1"))) + XCTAssertNotEqual(orderBy, OrderBy(.ascending("key2"))) + XCTAssertNotEqual(orderBy, OrderBy(.descending("key1"))) XCTAssertNotEqual(orderBy, OrderBy(NSSortDescriptor(key: "key1", ascending: false))) XCTAssertEqual(orderBy, OrderBy([sortDescriptor])) XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor]) @@ -63,7 +63,7 @@ final class OrderByTests: XCTestCase { ] let orderBy = OrderBy(sortDescriptors) XCTAssertEqual(orderBy, OrderBy(sortDescriptors)) - XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key2"))) + XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2"))) XCTAssertNotEqual( orderBy, OrderBy( @@ -73,30 +73,30 @@ final class OrderByTests: XCTestCase { ] ) ) - XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Ascending("key2"))) - XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key3"))) + XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2"))) + XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3"))) XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors) } do { - let orderBy = OrderBy(.Ascending("key1")) + let orderBy = OrderBy(.ascending("key1")) let sortDescriptor = NSSortDescriptor(key: "key1", ascending: true) XCTAssertEqual(orderBy, OrderBy(sortDescriptor)) - XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"))) - XCTAssertNotEqual(orderBy, OrderBy(.Descending("key1"))) - XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key2"))) + XCTAssertEqual(orderBy, OrderBy(.ascending("key1"))) + XCTAssertNotEqual(orderBy, OrderBy(.descending("key1"))) + XCTAssertNotEqual(orderBy, OrderBy(.ascending("key2"))) XCTAssertEqual(orderBy, OrderBy([sortDescriptor])) XCTAssertEqual(orderBy.sortDescriptors, [sortDescriptor]) } do { - let orderBy = OrderBy(.Ascending("key1"), .Descending("key2")) + let orderBy = OrderBy(.ascending("key1"), .descending("key2")) let sortDescriptors = [ NSSortDescriptor(key: "key1", ascending: true), NSSortDescriptor(key: "key2", ascending: false) ] XCTAssertEqual(orderBy, OrderBy(sortDescriptors)) - XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key2"))) + XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2"))) XCTAssertNotEqual( orderBy, OrderBy( @@ -106,20 +106,20 @@ final class OrderByTests: XCTestCase { ] ) ) - XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Ascending("key2"))) - XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key3"))) + XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2"))) + XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3"))) XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors) } do { - let sortKeys: [SortKey] = [.Ascending("key1"), .Descending("key2")] + let sortKeys: [SortKey] = [.ascending("key1"), .descending("key2")] let orderBy = OrderBy(sortKeys) let sortDescriptors = [ NSSortDescriptor(key: "key1", ascending: true), NSSortDescriptor(key: "key2", ascending: false) ] XCTAssertEqual(orderBy, OrderBy(sortDescriptors)) - XCTAssertEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key2"))) + XCTAssertEqual(orderBy, OrderBy(.ascending("key1"), .descending("key2"))) XCTAssertNotEqual( orderBy, OrderBy( @@ -129,8 +129,8 @@ final class OrderByTests: XCTestCase { ] ) ) - XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Ascending("key2"))) - XCTAssertNotEqual(orderBy, OrderBy(.Ascending("key1"), .Descending("key3"))) + XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .ascending("key2"))) + XCTAssertNotEqual(orderBy, OrderBy(.ascending("key1"), .descending("key3"))) XCTAssertEqual(orderBy.sortDescriptors, sortDescriptors) } } @@ -138,15 +138,15 @@ final class OrderByTests: XCTestCase { @objc dynamic func test_ThatOrderByClauseOperations_ComputeCorrectly() { - let orderBy1 = OrderBy(.Ascending("key1")) - let orderBy2 = OrderBy(.Descending("key2")) - let orderBy3 = OrderBy(.Ascending("key3")) + let orderBy1 = OrderBy(.ascending("key1")) + let orderBy2 = OrderBy(.descending("key2")) + let orderBy3 = OrderBy(.ascending("key3")) do { let plusOrderBy = orderBy1 + orderBy2 + orderBy3 - XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1"), .Descending("key2"), .Ascending("key3"))) - XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1")) + OrderBy(.Descending("key2"), .Ascending("key3"))) + XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2"), .ascending("key3"))) + XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.descending("key2"), .ascending("key3"))) XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1) @@ -158,14 +158,14 @@ final class OrderByTests: XCTestCase { var plusOrderBy = orderBy1 plusOrderBy += orderBy2 - XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1"), .Descending("key2"))) - XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1")) + OrderBy(.Descending("key2"))) + XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2"))) + XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1")) + OrderBy(.descending("key2"))) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1) XCTAssertEqual(plusOrderBy.sortDescriptors, orderBy1.sortDescriptors + orderBy2.sortDescriptors) plusOrderBy += orderBy3 - XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1"), .Descending("key2"), .Ascending("key3"))) - XCTAssertEqual(plusOrderBy, OrderBy(.Ascending("key1"), .Descending("key2")) + OrderBy(.Ascending("key3"))) + XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2"), .ascending("key3"))) + XCTAssertEqual(plusOrderBy, OrderBy(.ascending("key1"), .descending("key2")) + OrderBy(.ascending("key3"))) XCTAssertNotEqual(plusOrderBy, orderBy1 + orderBy3 + orderBy2) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy1 + orderBy3) XCTAssertNotEqual(plusOrderBy, orderBy2 + orderBy3 + orderBy1) @@ -178,7 +178,7 @@ final class OrderByTests: XCTestCase { @objc dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() { - let orderBy = OrderBy(.Ascending("key")) + let orderBy = OrderBy(.ascending("key")) let request = CoreStoreFetchRequest() orderBy.applyToFetchRequest(request) XCTAssertNotNil(request.sortDescriptors) diff --git a/CoreStoreTests/QueryTests.swift b/CoreStoreTests/QueryTests.swift index 585499f..d77b86c 100644 --- a/CoreStoreTests/QueryTests.swift +++ b/CoreStoreTests/QueryTests.swift @@ -43,13 +43,13 @@ class QueryTests: BaseTestDataTestCase { let from = From(configurations) let queryClauses: [QueryClause] = [ - Where("testEntityID", isEqualTo: 101) + Where(#keyPath(TestEntity1.testEntityID), isEqualTo: 101) ] do { let value = stack.queryValue( from, - Select("testBoolean"), + Select(#keyPath(TestEntity1.testBoolean)), queryClauses ) XCTAssertNotNil(value) @@ -59,7 +59,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testNumber"), + Select(#keyPath(TestEntity1.testNumber)), queryClauses ) XCTAssertNotNil(value) @@ -69,7 +69,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testNumber"), + Select(#keyPath(TestEntity1.testNumber)), queryClauses ) XCTAssertNotNil(value) @@ -79,7 +79,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testNumber"), + Select(#keyPath(TestEntity1.testNumber)), queryClauses ) XCTAssertNotNil(value) @@ -89,7 +89,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testNumber"), + Select(#keyPath(TestEntity1.testNumber)), queryClauses ) XCTAssertNotNil(value) @@ -99,7 +99,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testNumber"), + Select(#keyPath(TestEntity1.testNumber)), queryClauses ) XCTAssertNotNil(value) @@ -109,7 +109,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testNumber"), + Select(#keyPath(TestEntity1.testNumber)), queryClauses ) XCTAssertNotNil(value) @@ -119,7 +119,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testNumber"), + Select(#keyPath(TestEntity1.testNumber)), queryClauses ) XCTAssertNotNil(value) @@ -129,7 +129,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testNumber"), + Select(#keyPath(TestEntity1.testNumber)), queryClauses ) XCTAssertNotNil(value) @@ -139,7 +139,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testDecimal"), + Select(#keyPath(TestEntity1.testDecimal)), queryClauses ) XCTAssertNotNil(value) @@ -149,7 +149,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testString"), + Select(#keyPath(TestEntity1.testString)), queryClauses ) XCTAssertNotNil(value) @@ -159,7 +159,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testString"), + Select(#keyPath(TestEntity1.testString)), queryClauses ) XCTAssertNotNil(value) @@ -169,27 +169,47 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testData"), + Select(#keyPath(TestEntity1.testData)), queryClauses ) XCTAssertNotNil(value) - XCTAssertEqual(value, ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)) + XCTAssertEqual(value as Data?, "nil:TestEntity1:1".data(using: .utf8)) } do { let value = stack.queryValue( from, - Select("testDate"), + Select(#keyPath(TestEntity1.testData)), queryClauses ) XCTAssertNotNil(value) - XCTAssertEqual(value, self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")) + XCTAssertEqual(value as Data?, "nil:TestEntity1:1".data(using: .utf8)) } do { let value = stack.queryValue( from, - Select("testDate"), + Select(#keyPath(TestEntity1.testDate)), + queryClauses + ) + XCTAssertNotNil(value) + XCTAssertEqual(value as Date?, self.dateFormatter.date(from: "2000-01-01T00:00:00Z")) + } + do { + + let value = stack.queryValue( + from, + Select(#keyPath(TestEntity1.testDate)), + queryClauses + ) + XCTAssertNotNil(value) + XCTAssertEqual(value as Date?, self.dateFormatter.date(from: "2000-01-01T00:00:00Z")) + } + do { + + let value = stack.queryValue( + from, + Select(#keyPath(TestEntity1.testDate)), queryClauses ) XCTAssertNil(value) @@ -207,14 +227,14 @@ class QueryTests: BaseTestDataTestCase { let from = From(configurations) let queryClauses: [QueryClause] = [ - Where("%K > %@", "testNumber", 1), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] do { let value = stack.queryValue( from, - Select(.Average("testBoolean")), + Select(.average(#keyPath(TestEntity1.testBoolean))), queryClauses ) XCTAssertNotNil(value) @@ -224,7 +244,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testNumber")), + Select(.average(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -234,7 +254,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testNumber")), + Select(.average(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -244,7 +264,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testNumber")), + Select(.average(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -254,7 +274,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testNumber")), + Select(.average(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -264,7 +284,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testNumber")), + Select(.average(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -274,7 +294,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testNumber")), + Select(.average(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -284,7 +304,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testNumber")), + Select(.average(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -294,7 +314,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testNumber")), + Select(.average(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -304,7 +324,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testDecimal")), + Select(.average(#keyPath(TestEntity1.testDecimal))), queryClauses ) XCTAssertNotNil(value) @@ -314,7 +334,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testString")), + Select(.average(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNil(value) @@ -323,7 +343,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testString")), + Select(.average(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNil(value) @@ -332,7 +352,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testData")), + Select(.average(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNil(value) @@ -341,7 +361,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Average("testDate")), + Select(.average(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNil(value) @@ -350,7 +370,25 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select("testEntityID"), + Select(.average(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNil(value) + } + do { + + let value = stack.queryValue( + from, + Select(.average(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNil(value) + } + do { + + let value = stack.queryValue( + from, + Select(#keyPath(TestEntity1.testEntityID)), queryClauses ) XCTAssertNil(value) @@ -368,13 +406,13 @@ class QueryTests: BaseTestDataTestCase { let from = From(configurations) let queryClauses: [QueryClause] = [ - Where("%K > %@", "testNumber", 1) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1) ] do { let value = stack.queryValue( from, - Select(.Count("testBoolean")), + Select(.count(#keyPath(TestEntity1.testBoolean))), queryClauses ) XCTAssertNotNil(value) @@ -384,7 +422,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testNumber")), + Select(.count(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -394,7 +432,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testNumber")), + Select(.count(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -404,7 +442,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testNumber")), + Select(.count(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -414,7 +452,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testNumber")), + Select(.count(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -424,7 +462,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testNumber")), + Select(.count(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -434,7 +472,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testNumber")), + Select(.count(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -444,7 +482,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testNumber")), + Select(.count(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -454,7 +492,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testNumber")), + Select(.count(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -464,7 +502,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testDecimal")), + Select(.count(#keyPath(TestEntity1.testDecimal))), queryClauses ) XCTAssertNil(value) @@ -473,7 +511,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testString")), + Select(.count(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNil(value) @@ -482,7 +520,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testString")), + Select(.count(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNil(value) @@ -491,7 +529,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testData")), + Select(.count(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNil(value) @@ -500,7 +538,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testDate")), + Select(.count(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNil(value) @@ -509,7 +547,25 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Count("testEntityID")), + Select(.count(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNil(value) + } + do { + + let value = stack.queryValue( + from, + Select(.count(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNil(value) + } + do { + + let value = stack.queryValue( + from, + Select(.count(#keyPath(TestEntity1.testEntityID))), queryClauses ) XCTAssertNil(value) @@ -527,13 +583,13 @@ class QueryTests: BaseTestDataTestCase { let from = From(configurations) let queryClauses: [QueryClause] = [ - Where("%K > %@", "testNumber", 1) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1) ] do { let value = stack.queryValue( from, - Select(.Maximum("testBoolean")), + Select(.maximum(#keyPath(TestEntity1.testBoolean))), queryClauses ) XCTAssertNotNil(value) @@ -543,7 +599,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testNumber")), + Select(.maximum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -553,7 +609,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testNumber")), + Select(.maximum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -563,7 +619,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testNumber")), + Select(.maximum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -573,7 +629,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testNumber")), + Select(.maximum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -583,7 +639,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testNumber")), + Select(.maximum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -593,7 +649,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testNumber")), + Select(.maximum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -603,7 +659,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testNumber")), + Select(.maximum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -613,7 +669,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testNumber")), + Select(.maximum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -623,7 +679,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testDecimal")), + Select(.maximum(#keyPath(TestEntity1.testDecimal))), queryClauses ) XCTAssertNotNil(value) @@ -633,7 +689,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testString")), + Select(.maximum(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNotNil(value) @@ -643,7 +699,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testString")), + Select(.maximum(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNotNil(value) @@ -653,27 +709,47 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Maximum("testData")), + Select(.maximum(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNotNil(value) - XCTAssertEqual(value, ("nil:TestEntity1:5" as NSString).dataUsingEncoding(NSUTF8StringEncoding)) + XCTAssertEqual(value as Data?, "nil:TestEntity1:5".data(using: .utf8)) } do { let value = stack.queryValue( from, - Select(.Maximum("testDate")), + Select(.maximum(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNotNil(value) - XCTAssertEqual(value, self.dateFormatter.dateFromString("2000-01-05T00:00:00Z")) + XCTAssertEqual(value as Data?, "nil:TestEntity1:5".data(using: .utf8)) } do { let value = stack.queryValue( from, - Select(.Maximum("testEntityID")), + Select(.maximum(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNotNil(value) + XCTAssertEqual(value as Date?, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")) + } + do { + + let value = stack.queryValue( + from, + Select(.maximum(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNotNil(value) + XCTAssertEqual(value as Date?, self.dateFormatter.date(from: "2000-01-05T00:00:00Z")) + } + do { + + let value = stack.queryValue( + from, + Select(.maximum(#keyPath(TestEntity1.testEntityID))), queryClauses ) XCTAssertNil(value) @@ -691,13 +767,13 @@ class QueryTests: BaseTestDataTestCase { let from = From(configurations) let queryClauses: [QueryClause] = [ - Where("%K > %@", "testNumber", 1) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1) ] do { let value = stack.queryValue( from, - Select(.Minimum("testBoolean")), + Select(.minimum(#keyPath(TestEntity1.testBoolean))), queryClauses ) XCTAssertNotNil(value) @@ -707,7 +783,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testNumber")), + Select(.minimum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -717,7 +793,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testNumber")), + Select(.minimum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -727,7 +803,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testNumber")), + Select(.minimum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -737,7 +813,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testNumber")), + Select(.minimum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -747,7 +823,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testNumber")), + Select(.minimum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -757,7 +833,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testNumber")), + Select(.minimum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -767,7 +843,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testNumber")), + Select(.minimum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -777,7 +853,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testNumber")), + Select(.minimum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -787,7 +863,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testDecimal")), + Select(.minimum(#keyPath(TestEntity1.testDecimal))), queryClauses ) XCTAssertNotNil(value) @@ -797,7 +873,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testString")), + Select(.minimum(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNotNil(value) @@ -807,7 +883,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testString")), + Select(.minimum(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNotNil(value) @@ -817,27 +893,47 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Minimum("testData")), + Select(.minimum(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNotNil(value) - XCTAssertEqual(value, ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)) + XCTAssertEqual(value as Data?, "nil:TestEntity1:2".data(using: .utf8)) } do { let value = stack.queryValue( from, - Select(.Minimum("testDate")), + Select(.minimum(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNotNil(value) - XCTAssertEqual(value, self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")) + XCTAssertEqual(value as Data?, "nil:TestEntity1:2".data(using: .utf8)) } do { let value = stack.queryValue( from, - Select(.Minimum("testEntityID")), + Select(.minimum(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNotNil(value) + XCTAssertEqual(value as Date?, self.dateFormatter.date(from: "2000-01-02T00:00:00Z")) + } + do { + + let value = stack.queryValue( + from, + Select(.minimum(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNotNil(value) + XCTAssertEqual(value as Date?, self.dateFormatter.date(from: "2000-01-02T00:00:00Z")) + } + do { + + let value = stack.queryValue( + from, + Select(.minimum(#keyPath(TestEntity1.testEntityID))), queryClauses ) XCTAssertNil(value) @@ -855,13 +951,13 @@ class QueryTests: BaseTestDataTestCase { let from = From(configurations) let queryClauses: [QueryClause] = [ - Where("%K > %@", "testNumber", 1) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1) ] do { let value = stack.queryValue( from, - Select(.Sum("testBoolean")), + Select(.sum(#keyPath(TestEntity1.testBoolean))), queryClauses ) XCTAssertNotNil(value) @@ -871,7 +967,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testNumber")), + Select(.sum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -881,7 +977,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testNumber")), + Select(.sum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -891,7 +987,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testNumber")), + Select(.sum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -901,7 +997,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testNumber")), + Select(.sum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -911,7 +1007,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testNumber")), + Select(.sum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -921,7 +1017,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testNumber")), + Select(.sum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -931,7 +1027,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testNumber")), + Select(.sum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -941,7 +1037,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testNumber")), + Select(.sum(#keyPath(TestEntity1.testNumber))), queryClauses ) XCTAssertNotNil(value) @@ -951,7 +1047,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testDecimal")), + Select(.sum(#keyPath(TestEntity1.testDecimal))), queryClauses ) XCTAssertNotNil(value) @@ -961,7 +1057,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testString")), + Select(.sum(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNil(value) @@ -970,7 +1066,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testString")), + Select(.sum(#keyPath(TestEntity1.testString))), queryClauses ) XCTAssertNil(value) @@ -979,7 +1075,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testData")), + Select(.sum(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNil(value) @@ -988,7 +1084,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testDate")), + Select(.sum(#keyPath(TestEntity1.testData))), queryClauses ) XCTAssertNil(value) @@ -997,7 +1093,25 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.Sum("testEntityID")), + Select(.sum(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNil(value) + } + do { + + let value = stack.queryValue( + from, + Select(.sum(#keyPath(TestEntity1.testDate))), + queryClauses + ) + XCTAssertNil(value) + } + do { + + let value = stack.queryValue( + from, + Select(.sum(#keyPath(TestEntity1.testEntityID))), queryClauses ) XCTAssertNil(value) @@ -1015,13 +1129,13 @@ class QueryTests: BaseTestDataTestCase { let from = From(configurations) let queryClauses: [QueryClause] = [ - Where("%K > %@", "testNumber", 1) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 1) ] do { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1030,7 +1144,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1039,7 +1153,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1048,7 +1162,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1057,7 +1171,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1066,7 +1180,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1075,7 +1189,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1084,7 +1198,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1093,7 +1207,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1102,7 +1216,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1111,7 +1225,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1120,7 +1234,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1129,7 +1243,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1138,7 +1252,7 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), queryClauses ) XCTAssertNil(value) @@ -1147,7 +1261,25 @@ class QueryTests: BaseTestDataTestCase { let value = stack.queryValue( from, - Select(.ObjectID()), + Select(.objectID()), + queryClauses + ) + XCTAssertNil(value) + } + do { + + let value = stack.queryValue( + from, + Select(.objectID()), + queryClauses + ) + XCTAssertNil(value) + } + do { + + let value = stack.queryValue( + from, + Select(.objectID()), queryClauses ) XCTAssertNotNil(value) @@ -1165,45 +1297,45 @@ class QueryTests: BaseTestDataTestCase { let from = From(configurations) let queryClauses: [QueryClause] = [ - Where("%K > %@", "testNumber", 3), - OrderBy(.Ascending("testEntityID")) + Where("%K > %@", #keyPath(TestEntity1.testNumber), 3), + OrderBy(.ascending(#keyPath(TestEntity1.testEntityID))) ] do { let values = stack.queryAttributes( from, Select( - "testBoolean", - "testNumber", - "testDecimal", - "testString", - "testData", - "testDate", - "testNil" + #keyPath(TestEntity1.testBoolean), + #keyPath(TestEntity1.testNumber), + #keyPath(TestEntity1.testDecimal), + #keyPath(TestEntity1.testString), + #keyPath(TestEntity1.testData), + #keyPath(TestEntity1.testDate), + #keyPath(TestEntity1.testNil) ), queryClauses ) XCTAssertNotNil(values) XCTAssertEqual( - values!, + values as Any as! [NSDictionary], [ [ - "testBoolean": NSNumber(bool: false), - "testNumber": NSNumber(integer: 4), - "testDecimal": NSDecimalNumber(string: "4"), - "testString": "nil:TestEntity1:4", - "testData": ("nil:TestEntity1:4" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-04T00:00:00Z")! + #keyPath(TestEntity1.testBoolean): NSNumber(value: false), + #keyPath(TestEntity1.testNumber): NSNumber(value: 4), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "4"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:4", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:4" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-04T00:00:00Z")! ], [ - "testBoolean": NSNumber(bool: true), - "testNumber": NSNumber(integer: 5), - "testDecimal": NSDecimalNumber(string: "5"), - "testString": "nil:TestEntity1:5", - "testData": ("nil:TestEntity1:5" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!, - "testDate": self.dateFormatter.dateFromString("2000-01-05T00:00:00Z")! + #keyPath(TestEntity1.testBoolean): NSNumber(value: true), + #keyPath(TestEntity1.testNumber): NSNumber(value: 5), + #keyPath(TestEntity1.testDecimal): NSDecimalNumber(string: "5"), + #keyPath(TestEntity1.testString): "nil:TestEntity1:5", + #keyPath(TestEntity1.testData): ("nil:TestEntity1:5" as NSString).data(using: String.Encoding.utf8.rawValue)!, + #keyPath(TestEntity1.testDate): self.dateFormatter.date(from: "2000-01-05T00:00:00Z")! ] - ] + ] as [NSDictionary] ) } } @@ -1224,17 +1356,17 @@ class QueryTests: BaseTestDataTestCase { let values = stack.queryAttributes( from, Select( - .Sum("testBoolean"), - .Count("testNumber"), - .Maximum("testNumber"), - .Minimum("testNumber"), - .Average("testDecimal") + .sum(#keyPath(TestEntity1.testBoolean)), + .count(#keyPath(TestEntity1.testNumber)), + .maximum(#keyPath(TestEntity1.testNumber)), + .minimum(#keyPath(TestEntity1.testNumber)), + .average(#keyPath(TestEntity1.testDecimal)) ), queryClauses ) XCTAssertNotNil(values) XCTAssertEqual( - values!, + values as Any as! [NSDictionary], [ [ "sum(testBoolean)": 3, @@ -1243,7 +1375,7 @@ class QueryTests: BaseTestDataTestCase { "min(testNumber)": 1, "average(testDecimal)": 3, ] - ] + ] as [NSDictionary] ) } do { @@ -1251,17 +1383,17 @@ class QueryTests: BaseTestDataTestCase { let values = stack.queryAttributes( from, Select( - .Sum("testBoolean", As: "testSum"), - .Count("testNumber", As: "testCount"), - .Maximum("testNumber", As: "testMaximum"), - .Minimum("testNumber", As: "testMinimum"), - .Average("testDecimal", As: "testAverage") + .sum(#keyPath(TestEntity1.testBoolean), as: "testSum"), + .count(#keyPath(TestEntity1.testNumber), as: "testCount"), + .maximum(#keyPath(TestEntity1.testNumber), as: "testMaximum"), + .minimum(#keyPath(TestEntity1.testNumber), as: "testMinimum"), + .average(#keyPath(TestEntity1.testDecimal), as: "testAverage") ), queryClauses ) XCTAssertNotNil(values) XCTAssertEqual( - values!, + values as Any as! [NSDictionary], [ [ "testSum": 3, @@ -1270,7 +1402,7 @@ class QueryTests: BaseTestDataTestCase { "testMinimum": 1, "testAverage": 3, ] - ] + ] as [NSDictionary] ) } } diff --git a/CoreStoreTests/SectionByTests.swift b/CoreStoreTests/SectionByTests.swift index 67bf1d9..9a3d6b0 100644 --- a/CoreStoreTests/SectionByTests.swift +++ b/CoreStoreTests/SectionByTests.swift @@ -42,14 +42,14 @@ final class SectionByTests: XCTestCase { let sectionBy = SectionBy("key") XCTAssertEqual(sectionBy.sectionKeyPath, "key") - XCTAssertEqual(sectionBy.sectionIndexTransformer(sectionName: "key"), "key") + XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key") } do { let sectionBy = SectionBy("key") { $0.flatMap { "\($0):suffix" } } XCTAssertEqual(sectionBy.sectionKeyPath, "key") - XCTAssertEqual(sectionBy.sectionIndexTransformer(sectionName: "key"), "key:suffix") - XCTAssertNil(sectionBy.sectionIndexTransformer(sectionName: nil)) + XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key:suffix") + XCTAssertNil(sectionBy.sectionIndexTransformer(nil)) } } } diff --git a/CoreStoreTests/SelectTests.swift b/CoreStoreTests/SelectTests.swift index 210125c..0c10154 100644 --- a/CoreStoreTests/SelectTests.swift +++ b/CoreStoreTests/SelectTests.swift @@ -39,17 +39,17 @@ final class SelectTests: XCTestCase { do { let term: SelectTerm = "attribute" - XCTAssertEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + XCTAssertEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute2")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Attribute(let key): + case ._attribute(let key): XCTAssertEqual(key, "attribute") default: @@ -58,17 +58,17 @@ final class SelectTests: XCTestCase { } do { - let term = SelectTerm.Attribute("attribute") - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.attribute("attribute") + XCTAssertNotEqual(term, SelectTerm.attribute("attribute2")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Attribute(let key): + case ._attribute(let key): XCTAssertEqual(key, "attribute") default: @@ -82,23 +82,23 @@ final class SelectTests: XCTestCase { do { - let term = SelectTerm.Average("attribute") - XCTAssertEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.average("attribute") + XCTAssertEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.average("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "average:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "average(attribute)") - XCTAssertTrue(nativeType == .DecimalAttributeType) + XCTAssertTrue(nativeType == .decimalAttributeType) default: XCTFail() @@ -106,23 +106,23 @@ final class SelectTests: XCTestCase { } do { - let term = SelectTerm.Average("attribute", As: "alias") - XCTAssertEqual(term, SelectTerm.Average("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute", As: "alias2")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.average("attribute", as: "alias") + XCTAssertEqual(term, SelectTerm.average("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.average("attribute", as: "alias2")) + XCTAssertNotEqual(term, SelectTerm.average("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "average:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "alias") - XCTAssertTrue(nativeType == .DecimalAttributeType) + XCTAssertTrue(nativeType == .decimalAttributeType) default: XCTFail() @@ -135,23 +135,23 @@ final class SelectTests: XCTestCase { do { - let term = SelectTerm.Count("attribute") - XCTAssertEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.count("attribute") + XCTAssertEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.count("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "count:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "count(attribute)") - XCTAssertTrue(nativeType == .Integer64AttributeType) + XCTAssertTrue(nativeType == .integer64AttributeType) default: XCTFail() @@ -159,23 +159,23 @@ final class SelectTests: XCTestCase { } do { - let term = SelectTerm.Count("attribute", As: "alias") - XCTAssertEqual(term, SelectTerm.Count("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute", As: "alias2")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.count("attribute", as: "alias") + XCTAssertEqual(term, SelectTerm.count("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.count("attribute", as: "alias2")) + XCTAssertNotEqual(term, SelectTerm.count("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "count:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "alias") - XCTAssertTrue(nativeType == .Integer64AttributeType) + XCTAssertTrue(nativeType == .integer64AttributeType) default: XCTFail() @@ -188,23 +188,23 @@ final class SelectTests: XCTestCase { do { - let term = SelectTerm.Maximum("attribute") - XCTAssertEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.maximum("attribute") + XCTAssertEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "max:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "max(attribute)") - XCTAssertTrue(nativeType == .UndefinedAttributeType) + XCTAssertTrue(nativeType == .undefinedAttributeType) default: XCTFail() @@ -212,23 +212,23 @@ final class SelectTests: XCTestCase { } do { - let term = SelectTerm.Maximum("attribute", As: "alias") - XCTAssertEqual(term, SelectTerm.Maximum("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute", As: "alias2")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.maximum("attribute", as: "alias") + XCTAssertEqual(term, SelectTerm.maximum("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute", as: "alias2")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "max:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "alias") - XCTAssertTrue(nativeType == .UndefinedAttributeType) + XCTAssertTrue(nativeType == .undefinedAttributeType) default: XCTFail() @@ -241,23 +241,23 @@ final class SelectTests: XCTestCase { do { - let term = SelectTerm.Minimum("attribute") - XCTAssertEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.minimum("attribute") + XCTAssertEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "min:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "min(attribute)") - XCTAssertTrue(nativeType == .UndefinedAttributeType) + XCTAssertTrue(nativeType == .undefinedAttributeType) default: XCTFail() @@ -265,23 +265,23 @@ final class SelectTests: XCTestCase { } do { - let term = SelectTerm.Minimum("attribute", As: "alias") - XCTAssertEqual(term, SelectTerm.Minimum("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute", As: "alias2")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.minimum("attribute", as: "alias") + XCTAssertEqual(term, SelectTerm.minimum("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute", as: "alias2")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "min:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "alias") - XCTAssertTrue(nativeType == .UndefinedAttributeType) + XCTAssertTrue(nativeType == .undefinedAttributeType) default: XCTFail() @@ -294,23 +294,23 @@ final class SelectTests: XCTestCase { do { - let term = SelectTerm.Sum("attribute") - XCTAssertEqual(term, SelectTerm.Sum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.sum("attribute") + XCTAssertEqual(term, SelectTerm.sum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "sum:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "sum(attribute)") - XCTAssertTrue(nativeType == .DecimalAttributeType) + XCTAssertTrue(nativeType == .decimalAttributeType) default: XCTFail() @@ -318,23 +318,23 @@ final class SelectTests: XCTestCase { } do { - let term = SelectTerm.Sum("attribute", As: "alias") - XCTAssertEqual(term, SelectTerm.Sum("attribute", As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute", As: "alias2")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute2")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) + let term = SelectTerm.sum("attribute", as: "alias") + XCTAssertEqual(term, SelectTerm.sum("attribute", as: "alias")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute", as: "alias2")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute2")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.objectID()) switch term { - case ._Aggregate(let function, let keyPath, let alias, let nativeType): + case ._aggregate(let function, let keyPath, let alias, let nativeType): XCTAssertEqual(function, "sum:") XCTAssertEqual(keyPath, "attribute") XCTAssertEqual(alias, "alias") - XCTAssertTrue(nativeType == .DecimalAttributeType) + XCTAssertTrue(nativeType == .decimalAttributeType) default: XCTFail() @@ -347,20 +347,20 @@ final class SelectTests: XCTestCase { do { - let term = SelectTerm.ObjectID() - XCTAssertEqual(term, SelectTerm.ObjectID()) - XCTAssertNotEqual(term, SelectTerm.ObjectID(As: "alias")) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) + let term = SelectTerm.objectID() + XCTAssertEqual(term, SelectTerm.objectID()) + XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias")) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) switch term { - case ._Identity(let alias, let nativeType): + case ._identity(let alias, let nativeType): XCTAssertEqual(alias, "objectID") - XCTAssertTrue(nativeType == .ObjectIDAttributeType) + XCTAssertTrue(nativeType == .objectIDAttributeType) default: XCTFail() @@ -368,21 +368,21 @@ final class SelectTests: XCTestCase { } do { - let term = SelectTerm.ObjectID(As: "alias") - XCTAssertEqual(term, SelectTerm.ObjectID(As: "alias")) - XCTAssertNotEqual(term, SelectTerm.ObjectID(As: "alias2")) - XCTAssertNotEqual(term, SelectTerm.ObjectID()) - XCTAssertNotEqual(term, SelectTerm.Attribute("attribute")) - XCTAssertNotEqual(term, SelectTerm.Average("attribute")) - XCTAssertNotEqual(term, SelectTerm.Count("attribute")) - XCTAssertNotEqual(term, SelectTerm.Maximum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Minimum("attribute")) - XCTAssertNotEqual(term, SelectTerm.Sum("attribute")) + let term = SelectTerm.objectID(as: "alias") + XCTAssertEqual(term, SelectTerm.objectID(as: "alias")) + XCTAssertNotEqual(term, SelectTerm.objectID(as: "alias2")) + XCTAssertNotEqual(term, SelectTerm.objectID()) + XCTAssertNotEqual(term, SelectTerm.attribute("attribute")) + XCTAssertNotEqual(term, SelectTerm.average("attribute")) + XCTAssertNotEqual(term, SelectTerm.count("attribute")) + XCTAssertNotEqual(term, SelectTerm.maximum("attribute")) + XCTAssertNotEqual(term, SelectTerm.minimum("attribute")) + XCTAssertNotEqual(term, SelectTerm.sum("attribute")) switch term { - case ._Identity(let alias, let nativeType): + case ._identity(let alias, let nativeType): XCTAssertEqual(alias, "alias") - XCTAssertTrue(nativeType == .ObjectIDAttributeType) + XCTAssertTrue(nativeType == .objectIDAttributeType) default: XCTFail() @@ -393,9 +393,9 @@ final class SelectTests: XCTestCase { @objc dynamic func test_ThatSelectClauses_ConfigureCorrectly() { - let term1 = SelectTerm.Attribute("attribute1") - let term2 = SelectTerm.Attribute("attribute2") - let term3 = SelectTerm.Attribute("attribute3") + let term1 = SelectTerm.attribute("attribute1") + let term2 = SelectTerm.attribute("attribute2") + let term3 = SelectTerm.attribute("attribute3") do { let select = Select(term1, term2, term3) diff --git a/CoreStoreTests/SetupTests.swift b/CoreStoreTests/SetupTests.swift index c5a3938..4be0452 100644 --- a/CoreStoreTests/SetupTests.swift +++ b/CoreStoreTests/SetupTests.swift @@ -29,20 +29,24 @@ import CoreStore // MARK: - SetupTests -class SetupTests: BaseTestCase { +class SetupTests: BaseTestDataTestCase { @objc dynamic func test_ThatDataStacks_ConfigureCorrectly() { do { - let model = NSManagedObjectModel.mergedModelFromBundles([NSBundle(forClass: self.dynamicType)])! + let model = NSManagedObjectModel.mergedModel(from: [Bundle(for: type(of: self))])! let stack = DataStack(model: model, migrationChain: nil) XCTAssertEqual(stack.coordinator.managedObjectModel, model) XCTAssertEqual(stack.rootSavingContext.persistentStoreCoordinator, stack.coordinator) - XCTAssertNil(stack.rootSavingContext.parentContext) - XCTAssertEqual(stack.mainContext.parentContext, stack.rootSavingContext) + XCTAssertNil(stack.rootSavingContext.parent) + XCTAssertFalse(stack.rootSavingContext.isDataStackContext) + XCTAssertFalse(stack.rootSavingContext.isTransactionContext) + XCTAssertEqual(stack.mainContext.parent, stack.rootSavingContext) + XCTAssertTrue(stack.mainContext.isDataStackContext) + XCTAssertFalse(stack.mainContext.isTransactionContext) XCTAssertEqual(stack.model, model) XCTAssertTrue(stack.migrationChain.valid) XCTAssertTrue(stack.migrationChain.empty) @@ -56,11 +60,11 @@ class SetupTests: BaseTestCase { let migrationChain: MigrationChain = ["version1", "version2", "version3"] - let stack = self.expectLogger([.LogWarning]) { + let stack = self.expectLogger([.logWarning]) { DataStack( modelName: "Model", - bundle: NSBundle(forClass: self.dynamicType), + bundle: Bundle(for: type(of: self)), migrationChain: migrationChain ) } @@ -77,7 +81,7 @@ class SetupTests: BaseTestCase { let stack = DataStack( modelName: "Model", - bundle: NSBundle(forClass: self.dynamicType) + bundle: Bundle(for: type(of: self)) ) do { @@ -132,7 +136,7 @@ class SetupTests: BaseTestCase { let stack = DataStack( modelName: "Model", - bundle: NSBundle(forClass: self.dynamicType) + bundle: Bundle(for: type(of: self)) ) do { @@ -154,7 +158,7 @@ class SetupTests: BaseTestCase { let sqliteStore = SQLiteStore( fileName: "ConfigStore1.sqlite", configuration: "Config1", - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) do { @@ -173,7 +177,7 @@ class SetupTests: BaseTestCase { let sqliteStore = SQLiteStore( fileName: "ConfigStore2.sqlite", configuration: "Config2", - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) do { @@ -189,16 +193,72 @@ class SetupTests: BaseTestCase { } } + @objc + dynamic func test_ThatSQLiteStores_DeleteFilesCorrectly() { + + let fileManager = FileManager.default + let sqliteStore = SQLiteStore() + func createStore() throws -> [String: Any] { + + do { + + let stack = DataStack( + modelName: "Model", + bundle: Bundle(for: type(of: self)) + ) + try! stack.addStorageAndWait(sqliteStore) + self.prepareTestDataForStack(stack) + } + XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path)) + XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal"))) + XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm"))) + + return try NSPersistentStoreCoordinator.metadataForPersistentStore( + ofType: type(of: sqliteStore).storeType, + at: sqliteStore.fileURL, + options: sqliteStore.storeOptions + ) + } + do { + + let metadata = try createStore() + let stack = DataStack( + modelName: "Model", + bundle: Bundle(for: type(of: self)) + ) + try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: stack.model[metadata]) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path)) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal"))) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm"))) + } + catch { + + XCTFail() + } + do { + + let metadata = try createStore() + try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: nil) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path)) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal"))) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm"))) + } + catch { + + XCTFail() + } + } + @objc dynamic func test_ThatLegacySQLiteStores_SetupCorrectly() { let stack = DataStack( modelName: "Model", - bundle: NSBundle(forClass: self.dynamicType) + bundle: Bundle(for: type(of: self)) ) do { - let sqliteStore = SQLiteStore() + let sqliteStore = LegacySQLiteStore() do { try stack.addStorageAndWait(sqliteStore) @@ -213,10 +273,10 @@ class SetupTests: BaseTestCase { } do { - let sqliteStore = SQLiteStore( + let sqliteStore = LegacySQLiteStore( fileName: "ConfigStore1.sqlite", configuration: "Config1", - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) do { @@ -232,10 +292,10 @@ class SetupTests: BaseTestCase { } do { - let sqliteStore = SQLiteStore( + let sqliteStore = LegacySQLiteStore( fileName: "ConfigStore2.sqlite", configuration: "Config2", - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) do { @@ -250,4 +310,60 @@ class SetupTests: BaseTestCase { XCTAssert(sqliteStore.matchesPersistentStore(persistentStore!)) } } + + @objc + dynamic func test_ThatLegacySQLiteStores_DeleteFilesCorrectly() { + + let fileManager = FileManager.default + let sqliteStore = LegacySQLiteStore() + func createStore() throws -> [String: Any] { + + do { + + let stack = DataStack( + modelName: "Model", + bundle: Bundle(for: type(of: self)) + ) + try! stack.addStorageAndWait(sqliteStore) + self.prepareTestDataForStack(stack) + } + XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path)) + XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal"))) + XCTAssertTrue(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm"))) + + return try NSPersistentStoreCoordinator.metadataForPersistentStore( + ofType: type(of: sqliteStore).storeType, + at: sqliteStore.fileURL, + options: sqliteStore.storeOptions + ) + } + do { + + let metadata = try createStore() + let stack = DataStack( + modelName: "Model", + bundle: Bundle(for: type(of: self)) + ) + try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: stack.model[metadata]) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path)) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal"))) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm"))) + } + catch { + + XCTFail() + } + do { + + let metadata = try createStore() + try sqliteStore.eraseStorageAndWait(metadata: metadata, soureModelHint: nil) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path)) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-wal"))) + XCTAssertFalse(fileManager.fileExists(atPath: sqliteStore.fileURL.path.appending("-shm"))) + } + catch { + + XCTFail() + } + } } diff --git a/CoreStoreTests/StorageInterfaceTests.swift b/CoreStoreTests/StorageInterfaceTests.swift index 2037f8f..9c85fd6 100644 --- a/CoreStoreTests/StorageInterfaceTests.swift +++ b/CoreStoreTests/StorageInterfaceTests.swift @@ -37,7 +37,7 @@ final class StorageInterfaceTests: XCTestCase { dynamic func test_ThatDefaultInMemoryStores_ConfigureCorrectly() { let store = InMemoryStore() - XCTAssertEqual(store.dynamicType.storeType, NSInMemoryStoreType) + XCTAssertEqual(type(of: store).storeType, NSInMemoryStoreType) XCTAssertNil(store.configuration) XCTAssertNil(store.storeOptions) } @@ -46,7 +46,7 @@ final class StorageInterfaceTests: XCTestCase { dynamic func test_ThatCustomInMemoryStores_ConfigureCorrectly() { let store = InMemoryStore(configuration: "config1") - XCTAssertEqual(store.dynamicType.storeType, NSInMemoryStoreType) + XCTAssertEqual(type(of: store).storeType, NSInMemoryStoreType) XCTAssertEqual(store.configuration, "config1") XCTAssertNil(store.storeOptions) } @@ -55,23 +55,23 @@ final class StorageInterfaceTests: XCTestCase { dynamic func test_ThatSQLiteStoreDefaultDirectories_AreCorrect() { #if os(tvOS) - let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory + let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory #else - let systemDirectorySearchPath = NSSearchPathDirectory.ApplicationSupportDirectory + let systemDirectorySearchPath = FileManager.SearchPathDirectory.applicationSupportDirectory #endif - let defaultSystemDirectory = NSFileManager - .defaultManager() - .URLsForDirectory(systemDirectorySearchPath, inDomains: .UserDomainMask).first! + let defaultSystemDirectory = FileManager.default + .urls(for: systemDirectorySearchPath, in: .userDomainMask).first! - let defaultRootDirectory = defaultSystemDirectory.URLByAppendingPathComponent( - NSBundle.mainBundle().bundleIdentifier ?? "com.CoreStore.DataStack", - isDirectory: true)! - let applicationName = (NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String) ?? "CoreData" + let defaultRootDirectory = defaultSystemDirectory.appendingPathComponent( + Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack", + isDirectory: true + ) + let applicationName = (Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String) ?? "CoreData" let defaultFileURL = defaultRootDirectory - .URLByAppendingPathComponent(applicationName, isDirectory: false)! - .URLByAppendingPathExtension("sqlite")! + .appendingPathComponent(applicationName, isDirectory: false) + .appendingPathExtension("sqlite") XCTAssertEqual(SQLiteStore.defaultRootDirectory, defaultRootDirectory) XCTAssertEqual(SQLiteStore.defaultFileURL, defaultFileURL) @@ -81,77 +81,76 @@ final class StorageInterfaceTests: XCTestCase { dynamic func test_ThatDefaultSQLiteStores_ConfigureCorrectly() { let store = SQLiteStore() - XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) + XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType) XCTAssertNil(store.configuration) - XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) + XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) XCTAssertEqual(store.fileURL, SQLiteStore.defaultFileURL) - XCTAssertEqual(store.mappingModelBundles, NSBundle.allBundles()) - XCTAssertEqual(store.localStorageOptions, [.None]) + XCTAssertEqual(store.mappingModelBundles, Bundle.allBundles) + XCTAssertEqual(store.localStorageOptions, .none) } @objc dynamic func test_ThatFileURLSQLiteStores_ConfigureCorrectly() { let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()) - .URLByAppendingPathComponent(NSUUID().UUIDString, isDirectory: false)! - .URLByAppendingPathExtension("db")! - let bundles = [NSBundle(forClass: self.dynamicType)] + .appendingPathComponent(NSUUID().uuidString, isDirectory: false)! + .appendingPathExtension("db") + let bundles = [Bundle(for: type(of: self))] let store = SQLiteStore( fileURL: fileURL, configuration: "config1", mappingModelBundles: bundles, - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) - XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) + XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType) XCTAssertEqual(store.configuration, "config1") - XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) + XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) XCTAssertEqual(store.fileURL, fileURL) XCTAssertEqual(store.mappingModelBundles, bundles) - XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch]) + XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch]) } @objc dynamic func test_ThatFileNameSQLiteStores_ConfigureCorrectly() { - let fileName = NSUUID().UUIDString + ".db" - let bundles = [NSBundle(forClass: self.dynamicType)] + let fileName = UUID().uuidString + ".db" + let bundles = [Bundle(for: type(of: self))] let store = SQLiteStore( fileName: fileName, configuration: "config1", mappingModelBundles: bundles, - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) - XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) + XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType) XCTAssertEqual(store.configuration, "config1") - XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) + XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) - XCTAssertEqual(store.fileURL.URLByDeletingLastPathComponent, SQLiteStore.defaultRootDirectory) + XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.defaultRootDirectory) XCTAssertEqual(store.fileURL.lastPathComponent, fileName) XCTAssertEqual(store.mappingModelBundles, bundles) - XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch]) + XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch]) } @objc dynamic func test_ThatLegacySQLiteStoreDefaultDirectories_AreCorrect() { #if os(tvOS) - let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory + let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory #else - let systemDirectorySearchPath = NSSearchPathDirectory.ApplicationSupportDirectory + let systemDirectorySearchPath = FileManager.SearchPathDirectory.applicationSupportDirectory #endif - let legacyDefaultRootDirectory = NSFileManager.defaultManager().URLsForDirectory( - systemDirectorySearchPath, - inDomains: .UserDomainMask - ).first! + let legacyDefaultRootDirectory = FileManager.default.urls( + for: systemDirectorySearchPath, + in: .userDomainMask).first! let legacyDefaultFileURL = legacyDefaultRootDirectory - .URLByAppendingPathComponent(DataStack.applicationName, isDirectory: false)! - .URLByAppendingPathExtension("sqlite")! + .appendingPathComponent(DataStack.applicationName, isDirectory: false) + .appendingPathExtension("sqlite") XCTAssertEqual(LegacySQLiteStore.defaultRootDirectory, legacyDefaultRootDirectory) XCTAssertEqual(LegacySQLiteStore.defaultFileURL, legacyDefaultFileURL) @@ -161,57 +160,57 @@ final class StorageInterfaceTests: XCTestCase { dynamic func test_ThatDefaultLegacySQLiteStores_ConfigureCorrectly() { let store = LegacySQLiteStore() - XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) + XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType) XCTAssertNil(store.configuration) - XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) + XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) XCTAssertEqual(store.fileURL, LegacySQLiteStore.defaultFileURL) - XCTAssertEqual(store.mappingModelBundles, NSBundle.allBundles()) - XCTAssertEqual(store.localStorageOptions, [.None]) + XCTAssertEqual(store.mappingModelBundles, Bundle.allBundles) + XCTAssertEqual(store.localStorageOptions, .none) } @objc dynamic func test_ThatFileURLLegacySQLiteStores_ConfigureCorrectly() { let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()) - .URLByAppendingPathComponent(NSUUID().UUIDString, isDirectory: false)! - .URLByAppendingPathExtension("db")! - let bundles = [NSBundle(forClass: self.dynamicType)] + .appendingPathComponent(NSUUID().uuidString, isDirectory: false)! + .appendingPathExtension("db") + let bundles = [Bundle(for: type(of: self))] let store = LegacySQLiteStore( fileURL: fileURL, configuration: "config1", mappingModelBundles: bundles, - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) - XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) + XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType) XCTAssertEqual(store.configuration, "config1") - XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) + XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) XCTAssertEqual(store.fileURL, fileURL) XCTAssertEqual(store.mappingModelBundles, bundles) - XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch]) + XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch]) } @objc dynamic func test_ThatFileNameLegacySQLiteStores_ConfigureCorrectly() { - let fileName = NSUUID().UUIDString + ".db" - let bundles = [NSBundle(forClass: self.dynamicType)] + let fileName = UUID().uuidString + ".db" + let bundles = [Bundle(for: type(of: self))] let store = LegacySQLiteStore( fileName: fileName, configuration: "config1", mappingModelBundles: bundles, - localStorageOptions: .RecreateStoreOnModelMismatch + localStorageOptions: .recreateStoreOnModelMismatch ) - XCTAssertEqual(store.dynamicType.storeType, NSSQLiteStoreType) + XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType) XCTAssertEqual(store.configuration, "config1") - XCTAssertEqual(store.storeOptions, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) + XCTAssertEqual(store.storeOptions as NSDictionary?, [NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary) - XCTAssertEqual(store.fileURL.URLByDeletingLastPathComponent, LegacySQLiteStore.defaultRootDirectory) + XCTAssertEqual(store.fileURL.deletingLastPathComponent(), LegacySQLiteStore.defaultRootDirectory) XCTAssertEqual(store.fileURL.lastPathComponent, fileName) XCTAssertEqual(store.mappingModelBundles, bundles) - XCTAssertEqual(store.localStorageOptions, [.RecreateStoreOnModelMismatch]) + XCTAssertEqual(store.localStorageOptions, [.recreateStoreOnModelMismatch]) } } diff --git a/CoreStoreTests/TestEntities/TestEntity1.swift b/CoreStoreTests/TestEntities/TestEntity1.swift index 8f5c302..13f52ec 100644 --- a/CoreStoreTests/TestEntities/TestEntity1.swift +++ b/CoreStoreTests/TestEntities/TestEntity1.swift @@ -31,9 +31,9 @@ class TestEntity1: NSManagedObject { @NSManaged var testEntityID: NSNumber? @NSManaged var testString: String? @NSManaged var testNumber: NSNumber? - @NSManaged var testDate: NSDate? + @NSManaged var testDate: Date? @NSManaged var testBoolean: NSNumber? @NSManaged var testDecimal: NSDecimalNumber? - @NSManaged var testData: NSData? + @NSManaged var testData: Data? @NSManaged var testNil: String? } diff --git a/CoreStoreTests/TestEntities/TestEntity2.swift b/CoreStoreTests/TestEntities/TestEntity2.swift index 3919646..05419ca 100644 --- a/CoreStoreTests/TestEntities/TestEntity2.swift +++ b/CoreStoreTests/TestEntities/TestEntity2.swift @@ -31,9 +31,9 @@ class TestEntity2: NSManagedObject { @NSManaged var testEntityID: NSNumber? @NSManaged var testString: String? @NSManaged var testNumber: NSNumber? - @NSManaged var testDate: NSDate? + @NSManaged var testDate: Date? @NSManaged var testBoolean: NSNumber? @NSManaged var testDecimal: NSDecimalNumber? - @NSManaged var testData: NSData? + @NSManaged var testData: Data? @NSManaged var testNil: String? } diff --git a/CoreStoreTests/TransactionTests.swift b/CoreStoreTests/TransactionTests.swift index 174bd89..26a75fb 100644 --- a/CoreStoreTests/TransactionTests.swift +++ b/CoreStoreTests/TransactionTests.swift @@ -24,7 +24,6 @@ // import XCTest -import GCDKit @testable import CoreStore @@ -39,21 +38,29 @@ final class TransactionTests: BaseTestCase { self.prepareStack { (stack) in - let testDate = NSDate() + let testDate = Date() do { - let createExpectation = self.expectationWithDescription("create") + let createExpectation = self.expectation(description: "create") stack.beginSynchronous { (transaction) in - let object = transaction.create(Into(TestEntity1)) - object.testEntityID = NSNumber(integer: 1) + XCTAssertEqual(transaction.context, transaction.internalContext()) + XCTAssertTrue(transaction.context.isTransactionContext) + XCTAssertFalse(transaction.context.isDataStackContext) + + let object = transaction.create(Into()) + XCTAssertEqual(object.fetchSource()?.internalContext(), transaction.context) + XCTAssertEqual(object.querySource()?.internalContext(), transaction.context) + + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 object.testDate = testDate + switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) createExpectation.fulfill() @@ -63,32 +70,35 @@ final class TransactionTests: BaseTestCase { } self.checkExpectationsImmediately() - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(stack.fetchCount(From()), 1) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.fetchSource()?.internalContext(), stack.mainContext) + XCTAssertEqual(object?.querySource()?.internalContext(), stack.mainContext) + + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1") XCTAssertEqual(object?.testNumber, 100) XCTAssertEqual(object?.testDate, testDate) } do { - let updateExpectation = self.expectationWithDescription("update") + let updateExpectation = self.expectation(description: "update") stack.beginSynchronous { (transaction) in - guard let object = transaction.fetchOne(From(TestEntity1)) else { + guard let object = transaction.fetchOne(From()) else { XCTFail() return } object.testString = "string1_edit" object.testNumber = 200 - object.testDate = NSDate.distantFuture() + object.testDate = Date.distantFuture switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) updateExpectation.fulfill() @@ -98,26 +108,26 @@ final class TransactionTests: BaseTestCase { } self.checkExpectationsImmediately() - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(stack.fetchCount(From()), 1) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1_edit") XCTAssertEqual(object?.testNumber, 200) - XCTAssertEqual(object?.testDate, NSDate.distantFuture()) + XCTAssertEqual(object?.testDate, Date.distantFuture) } do { - let deleteExpectation = self.expectationWithDescription("delete") + let deleteExpectation = self.expectation(description: "delete") stack.beginSynchronous { (transaction) in - let object = transaction.fetchOne(From(TestEntity1)) + let object = transaction.fetchOne(From()) transaction.delete(object) switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) deleteExpectation.fulfill() @@ -127,9 +137,9 @@ final class TransactionTests: BaseTestCase { } self.checkExpectationsImmediately() - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 0) + XCTAssertEqual(stack.fetchCount(From()), 0) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNil(object) } } @@ -140,21 +150,21 @@ final class TransactionTests: BaseTestCase { self.prepareStack(configurations: [nil, "Config1"]) { (stack) in - let testDate = NSDate() + let testDate = Date() do { - let createExpectation = self.expectationWithDescription("create") + let createExpectation = self.expectation(description: "create") stack.beginSynchronous { (transaction) in let object = transaction.create(Into("Config1")) - object.testEntityID = NSNumber(integer: 1) + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 object.testDate = testDate switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) createExpectation.fulfill() @@ -169,14 +179,14 @@ final class TransactionTests: BaseTestCase { let object = stack.fetchOne(From("Config1")) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1") XCTAssertEqual(object?.testNumber, 100) XCTAssertEqual(object?.testDate, testDate) } do { - let updateExpectation = self.expectationWithDescription("update") + let updateExpectation = self.expectation(description: "update") stack.beginSynchronous { (transaction) in guard let object = transaction.fetchOne(From("Config1")) else { @@ -186,11 +196,11 @@ final class TransactionTests: BaseTestCase { } object.testString = "string1_edit" object.testNumber = 200 - object.testDate = NSDate.distantFuture() + object.testDate = Date.distantFuture switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) updateExpectation.fulfill() @@ -205,14 +215,14 @@ final class TransactionTests: BaseTestCase { let object = stack.fetchOne(From("Config1")) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1_edit") XCTAssertEqual(object?.testNumber, 200) - XCTAssertEqual(object?.testDate, NSDate.distantFuture()) + XCTAssertEqual(object?.testDate, Date.distantFuture) } do { - let deleteExpectation = self.expectationWithDescription("delete") + let deleteExpectation = self.expectation(description: "delete") stack.beginSynchronous { (transaction) in let object = transaction.fetchOne(From("Config1")) @@ -220,7 +230,7 @@ final class TransactionTests: BaseTestCase { switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) deleteExpectation.fulfill() @@ -243,41 +253,41 @@ final class TransactionTests: BaseTestCase { do { - let createDiscardExpectation = self.expectationWithDescription("create-discard") - let loggerExpectations = self.prepareLoggerExpectations([.LogWarning]) + let createDiscardExpectation = self.expectation(description: "create-discard") + let loggerExpectations = self.prepareLoggerExpectations([.logWarning]) stack.beginSynchronous { (transaction) in - let object = transaction.create(Into(TestEntity1)) - object.testEntityID = NSNumber(integer: 1) + let object = transaction.create(Into()) + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 - object.testDate = NSDate() + object.testDate = Date() createDiscardExpectation.fulfill() self.expectLogger(loggerExpectations) } self.checkExpectationsImmediately() - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 0) + XCTAssertEqual(stack.fetchCount(From()), 0) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNil(object) } - let testDate = NSDate() + let testDate = Date() do { - let createExpectation = self.expectationWithDescription("create") + let createExpectation = self.expectation(description: "create") stack.beginSynchronous { (transaction) in - let object = transaction.create(Into(TestEntity1)) - object.testEntityID = NSNumber(integer: 1) + let object = transaction.create(Into()) + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 object.testDate = testDate switch transaction.commitAndWait() { - case .Success(true): + case .success(true): createExpectation.fulfill() default: @@ -288,40 +298,40 @@ final class TransactionTests: BaseTestCase { } do { - let updateDiscardExpectation = self.expectationWithDescription("update-discard") - let loggerExpectations = self.prepareLoggerExpectations([.LogWarning]) + let updateDiscardExpectation = self.expectation(description: "update-discard") + let loggerExpectations = self.prepareLoggerExpectations([.logWarning]) stack.beginSynchronous { (transaction) in - guard let object = transaction.fetchOne(From(TestEntity1)) else { + guard let object = transaction.fetchOne(From()) else { XCTFail() return } object.testString = "string1_edit" object.testNumber = 200 - object.testDate = NSDate.distantFuture() + object.testDate = Date.distantFuture updateDiscardExpectation.fulfill() self.expectLogger(loggerExpectations) } self.checkExpectationsImmediately() - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(stack.fetchCount(From()), 1) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1") XCTAssertEqual(object?.testNumber, 100) XCTAssertEqual(object?.testDate, testDate) } do { - let deleteDiscardExpectation = self.expectationWithDescription("delete-discard") - let loggerExpectations = self.prepareLoggerExpectations([.LogWarning]) + let deleteDiscardExpectation = self.expectation(description: "delete-discard") + let loggerExpectations = self.prepareLoggerExpectations([.logWarning]) stack.beginSynchronous { (transaction) in - guard let object = transaction.fetchOne(From(TestEntity1)) else { + guard let object = transaction.fetchOne(From()) else { XCTFail() return @@ -333,11 +343,11 @@ final class TransactionTests: BaseTestCase { } self.checkExpectationsImmediately() - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(stack.fetchCount(From()), 1) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1") XCTAssertEqual(object?.testNumber, 100) XCTAssertEqual(object?.testDate, testDate) @@ -451,14 +461,21 @@ final class TransactionTests: BaseTestCase { self.prepareStack { (stack) in - let testDate = NSDate() + let testDate = Date() do { - let createExpectation = self.expectationWithDescription("create") + let createExpectation = self.expectation(description: "create") stack.beginAsynchronous { (transaction) in - let object = transaction.create(Into(TestEntity1)) - object.testEntityID = NSNumber(integer: 1) + XCTAssertEqual(transaction.context, transaction.internalContext()) + XCTAssertTrue(transaction.context.isTransactionContext) + XCTAssertFalse(transaction.context.isDataStackContext) + + let object = transaction.create(Into()) + XCTAssertEqual(object.fetchSource()?.internalContext(), transaction.context) + XCTAssertEqual(object.querySource()?.internalContext(), transaction.context) + + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 object.testDate = testDate @@ -467,14 +484,17 @@ final class TransactionTests: BaseTestCase { switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(stack.fetchCount(From()), 1) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.fetchSource()?.internalContext(), stack.mainContext) + XCTAssertEqual(object?.querySource()?.internalContext(), stack.mainContext) + + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1") XCTAssertEqual(object?.testNumber, 100) XCTAssertEqual(object?.testDate, testDate) @@ -488,33 +508,33 @@ final class TransactionTests: BaseTestCase { } do { - let updateExpectation = self.expectationWithDescription("update") + let updateExpectation = self.expectation(description: "update") stack.beginAsynchronous { (transaction) in - guard let object = transaction.fetchOne(From(TestEntity1)) else { + guard let object = transaction.fetchOne(From()) else { XCTFail() return } object.testString = "string1_edit" object.testNumber = 200 - object.testDate = NSDate.distantFuture() + object.testDate = Date.distantFuture transaction.commit { (result) in switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(stack.fetchCount(From()), 1) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1_edit") XCTAssertEqual(object?.testNumber, 200) - XCTAssertEqual(object?.testDate, NSDate.distantFuture()) + XCTAssertEqual(object?.testDate, Date.distantFuture) updateExpectation.fulfill() default: @@ -525,22 +545,22 @@ final class TransactionTests: BaseTestCase { } do { - let deleteExpectation = self.expectationWithDescription("delete") + let deleteExpectation = self.expectation(description: "delete") stack.beginAsynchronous { (transaction) in - let object = transaction.fetchOne(From(TestEntity1)) + let object = transaction.fetchOne(From()) transaction.delete(object) transaction.commit { (result) in switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 0) + XCTAssertEqual(stack.fetchCount(From()), 0) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNil(object) deleteExpectation.fulfill() @@ -559,14 +579,14 @@ final class TransactionTests: BaseTestCase { self.prepareStack(configurations: [nil, "Config1"]) { (stack) in - let testDate = NSDate() + let testDate = Date() do { - let createExpectation = self.expectationWithDescription("create") + let createExpectation = self.expectation(description: "create") stack.beginAsynchronous { (transaction) in let object = transaction.create(Into("Config1")) - object.testEntityID = NSNumber(integer: 1) + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 object.testDate = testDate @@ -575,7 +595,7 @@ final class TransactionTests: BaseTestCase { switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) XCTAssertEqual(stack.fetchCount(From("Config1")), 1) @@ -583,7 +603,7 @@ final class TransactionTests: BaseTestCase { let object = stack.fetchOne(From("Config1")) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1") XCTAssertEqual(object?.testNumber, 100) XCTAssertEqual(object?.testDate, testDate) @@ -597,7 +617,7 @@ final class TransactionTests: BaseTestCase { } do { - let updateExpectation = self.expectationWithDescription("update") + let updateExpectation = self.expectation(description: "update") stack.beginAsynchronous { (transaction) in guard let object = transaction.fetchOne(From("Config1")) else { @@ -607,13 +627,13 @@ final class TransactionTests: BaseTestCase { } object.testString = "string1_edit" object.testNumber = 200 - object.testDate = NSDate.distantFuture() + object.testDate = Date.distantFuture transaction.commit { (result) in switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) XCTAssertEqual(stack.fetchCount(From("Config1")), 1) @@ -621,10 +641,10 @@ final class TransactionTests: BaseTestCase { let object = stack.fetchOne(From("Config1")) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1_edit") XCTAssertEqual(object?.testNumber, 200) - XCTAssertEqual(object?.testDate, NSDate.distantFuture()) + XCTAssertEqual(object?.testDate, Date.distantFuture) updateExpectation.fulfill() default: @@ -635,7 +655,7 @@ final class TransactionTests: BaseTestCase { } do { - let deleteExpectation = self.expectationWithDescription("delete") + let deleteExpectation = self.expectation(description: "delete") stack.beginAsynchronous { (transaction) in let object = transaction.fetchOne(From("Config1")) @@ -645,7 +665,7 @@ final class TransactionTests: BaseTestCase { switch result { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) XCTAssertEqual(stack.fetchCount(From("Config1")), 0) @@ -670,31 +690,31 @@ final class TransactionTests: BaseTestCase { do { - let createDiscardExpectation = self.expectationWithDescription("create-discard") - let loggerExpectations = self.prepareLoggerExpectations([.LogWarning]) + let createDiscardExpectation = self.expectation(description: "create-discard") + let loggerExpectations = self.prepareLoggerExpectations([.logWarning]) stack.beginAsynchronous { (transaction) in - let object = transaction.create(Into(TestEntity1)) - object.testEntityID = NSNumber(integer: 1) + let object = transaction.create(Into()) + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 - object.testDate = NSDate() + object.testDate = Date() createDiscardExpectation.fulfill() self.expectLogger(loggerExpectations) } } - let testDate = NSDate() + let testDate = Date() do { - let createExpectation = self.expectationWithDescription("create") + let createExpectation = self.expectation(description: "create") stack.beginAsynchronous { (transaction) in - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 0) - XCTAssertNil(transaction.fetchOne(From(TestEntity1))) + XCTAssertEqual(transaction.fetchCount(From()), 0) + XCTAssertNil(transaction.fetchOne(From())) - let object = transaction.create(Into(TestEntity1)) - object.testEntityID = NSNumber(integer: 1) + let object = transaction.create(Into()) + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 object.testDate = testDate @@ -703,7 +723,7 @@ final class TransactionTests: BaseTestCase { switch result { - case .Success(true): + case .success(true): createExpectation.fulfill() default: @@ -714,18 +734,18 @@ final class TransactionTests: BaseTestCase { } do { - let updateDiscardExpectation = self.expectationWithDescription("update-discard") - let loggerExpectations = self.prepareLoggerExpectations([.LogWarning]) + let updateDiscardExpectation = self.expectation(description: "update-discard") + let loggerExpectations = self.prepareLoggerExpectations([.logWarning]) stack.beginAsynchronous { (transaction) in - guard let object = transaction.fetchOne(From(TestEntity1)) else { + guard let object = transaction.fetchOne(From()) else { XCTFail() return } object.testString = "string1_edit" object.testNumber = 200 - object.testDate = NSDate.distantFuture() + object.testDate = Date.distantFuture updateDiscardExpectation.fulfill() self.expectLogger(loggerExpectations) @@ -733,32 +753,32 @@ final class TransactionTests: BaseTestCase { } do { - let deleteDiscardExpectation = self.expectationWithDescription("delete-discard") - let loggerExpectations = self.prepareLoggerExpectations([.LogWarning]) + let deleteDiscardExpectation = self.expectation(description: "delete-discard") + let loggerExpectations = self.prepareLoggerExpectations([.logWarning]) stack.beginAsynchronous { (transaction) in - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(transaction.fetchCount(From()), 1) - guard let object = transaction.fetchOne(From(TestEntity1)) else { + guard let object = transaction.fetchOne(From()) else { XCTFail() return } XCTAssertNotNil(object) - XCTAssertEqual(object.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object.testString, "string1") XCTAssertEqual(object.testNumber, 100) XCTAssertEqual(object.testDate, testDate) transaction.delete(object) - GCDQueue.Main.async { + DispatchQueue.main.async { - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(stack.fetchCount(From()), 1) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1") XCTAssertEqual(object?.testNumber, 100) XCTAssertEqual(object?.testDate, testDate) @@ -777,25 +797,34 @@ final class TransactionTests: BaseTestCase { self.prepareStack { (stack) in let transaction = stack.beginUnsafe() + XCTAssertEqual(transaction.context, transaction.internalContext()) + XCTAssertTrue(transaction.context.isTransactionContext) + XCTAssertFalse(transaction.context.isDataStackContext) - let testDate = NSDate() + let testDate = Date() do { - let object = transaction.create(Into(TestEntity1)) - object.testEntityID = NSNumber(integer: 1) + let object = transaction.create(Into()) + XCTAssertEqual(object.fetchSource()?.internalContext(), transaction.context) + XCTAssertEqual(object.querySource()?.internalContext(), transaction.context) + + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 object.testDate = testDate switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(stack.fetchCount(From()), 1) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.fetchSource()?.internalContext(), stack.mainContext) + XCTAssertEqual(object?.querySource()?.internalContext(), stack.mainContext) + + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1") XCTAssertEqual(object?.testNumber, 100) XCTAssertEqual(object?.testDate, testDate) @@ -806,27 +835,27 @@ final class TransactionTests: BaseTestCase { } do { - guard let object = transaction.fetchOne(From(TestEntity1)) else { + guard let object = transaction.fetchOne(From()) else { XCTFail() return } object.testString = "string1_edit" object.testNumber = 200 - object.testDate = NSDate.distantFuture() + object.testDate = Date.distantFuture switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) + XCTAssertEqual(stack.fetchCount(From()), 1) - let object = stack.fetchOne(From(TestEntity1)) + let object = stack.fetchOne(From()) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1_edit") XCTAssertEqual(object?.testNumber, 200) - XCTAssertEqual(object?.testDate, NSDate.distantFuture()) + XCTAssertEqual(object?.testDate, Date.distantFuture) default: XCTFail() @@ -834,16 +863,16 @@ final class TransactionTests: BaseTestCase { } do { - let object = transaction.fetchOne(From(TestEntity1)) + let object = transaction.fetchOne(From()) transaction.delete(object) switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 0) - XCTAssertNil(stack.fetchOne(From(TestEntity1))) + XCTAssertEqual(stack.fetchCount(From()), 0) + XCTAssertNil(stack.fetchOne(From())) default: XCTFail() @@ -859,25 +888,25 @@ final class TransactionTests: BaseTestCase { let transaction = stack.beginUnsafe() - let testDate = NSDate() + let testDate = Date() do { let object = transaction.create(Into("Config1")) - object.testEntityID = NSNumber(integer: 1) + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 object.testDate = testDate switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) XCTAssertEqual(stack.fetchCount(From("Config1")), 1) XCTAssertEqual(stack.fetchCount(From(nil)), 0) let object = stack.fetchOne(From("Config1")) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1") XCTAssertEqual(object?.testNumber, 100) XCTAssertEqual(object?.testDate, testDate) @@ -895,21 +924,21 @@ final class TransactionTests: BaseTestCase { } object.testString = "string1_edit" object.testNumber = 200 - object.testDate = NSDate.distantFuture() + object.testDate = Date.distantFuture switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) XCTAssertEqual(stack.fetchCount(From("Config1")), 1) XCTAssertEqual(stack.fetchCount(From(nil)), 0) let object = stack.fetchOne(From("Config1")) XCTAssertNotNil(object) - XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object?.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object?.testString, "string1_edit") XCTAssertEqual(object?.testNumber, 200) - XCTAssertEqual(object?.testDate, NSDate.distantFuture()) + XCTAssertEqual(object?.testDate, Date.distantFuture) default: XCTFail() @@ -922,7 +951,7 @@ final class TransactionTests: BaseTestCase { switch transaction.commitAndWait() { - case .Success(let hasChanges): + case .success(let hasChanges): XCTAssertTrue(hasChanges) XCTAssertEqual(stack.fetchCount(From("Config1")), 0) @@ -943,33 +972,33 @@ final class TransactionTests: BaseTestCase { let transaction = stack.beginUnsafe(supportsUndo: true) do { - let object = transaction.create(Into(TestEntity1)) - object.testEntityID = NSNumber(integer: 1) + let object = transaction.create(Into()) + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 - object.testDate = NSDate() + object.testDate = Date() transaction.rollback() - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 0) - XCTAssertNil(transaction.fetchOne(From(TestEntity1))) + XCTAssertEqual(transaction.fetchCount(From()), 0) + XCTAssertNil(transaction.fetchOne(From())) - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 0) - XCTAssertNil(stack.fetchOne(From(TestEntity1))) + XCTAssertEqual(stack.fetchCount(From()), 0) + XCTAssertNil(stack.fetchOne(From())) } - let testDate = NSDate() + let testDate = Date() do { - let object = transaction.create(Into(TestEntity1)) - object.testEntityID = NSNumber(integer: 1) + let object = transaction.create(Into()) + object.testEntityID = NSNumber(value: 1) object.testString = "string1" object.testNumber = 100 object.testDate = testDate switch transaction.commitAndWait() { - case .Success(true): + case .success(true): break default: @@ -979,21 +1008,21 @@ final class TransactionTests: BaseTestCase { do { - guard let object = transaction.fetchOne(From(TestEntity1)) else { + guard let object = transaction.fetchOne(From()) else { XCTFail() return } object.testString = "string1_edit" object.testNumber = 200 - object.testDate = NSDate.distantFuture() + object.testDate = Date.distantFuture transaction.rollback() - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1) - if let object = transaction.fetchOne(From(TestEntity1)) { + XCTAssertEqual(transaction.fetchCount(From()), 1) + if let object = transaction.fetchOne(From()) { - XCTAssertEqual(object.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object.testString, "string1") XCTAssertEqual(object.testNumber, 100) XCTAssertEqual(object.testDate, testDate) @@ -1003,10 +1032,10 @@ final class TransactionTests: BaseTestCase { XCTFail() } - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) - if let object = stack.fetchOne(From(TestEntity1)) { + XCTAssertEqual(stack.fetchCount(From()), 1) + if let object = stack.fetchOne(From()) { - XCTAssertEqual(object.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object.testString, "string1") XCTAssertEqual(object.testNumber, 100) XCTAssertEqual(object.testDate, testDate) @@ -1019,7 +1048,7 @@ final class TransactionTests: BaseTestCase { do { - guard let object = transaction.fetchOne(From(TestEntity1)) else { + guard let object = transaction.fetchOne(From()) else { XCTFail() return @@ -1028,10 +1057,10 @@ final class TransactionTests: BaseTestCase { transaction.rollback() - XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1) - if let object = transaction.fetchOne(From(TestEntity1)) { + XCTAssertEqual(transaction.fetchCount(From()), 1) + if let object = transaction.fetchOne(From()) { - XCTAssertEqual(object.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object.testString, "string1") XCTAssertEqual(object.testNumber, 100) XCTAssertEqual(object.testDate, testDate) @@ -1041,10 +1070,10 @@ final class TransactionTests: BaseTestCase { XCTFail() } - XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1) - if let object = stack.fetchOne(From(TestEntity1)) { + XCTAssertEqual(stack.fetchCount(From()), 1) + if let object = stack.fetchOne(From()) { - XCTAssertEqual(object.testEntityID, NSNumber(integer: 1)) + XCTAssertEqual(object.testEntityID, NSNumber(value: 1)) XCTAssertEqual(object.testString, "string1") XCTAssertEqual(object.testNumber, 100) XCTAssertEqual(object.testDate, testDate) diff --git a/CoreStoreTests/WhereTests.swift b/CoreStoreTests/WhereTests.swift index 24044e5..f336551 100644 --- a/CoreStoreTests/WhereTests.swift +++ b/CoreStoreTests/WhereTests.swift @@ -87,6 +87,211 @@ final class WhereTests: XCTestCase { } } + @objc + dynamic func test_ThatWhereClauses_BridgeArgumentsCorrectly() { + + do { + + let value: Int = 100 + let whereClause1 = Where("%K == %d", "key", value) + let whereClause2 = Where("%K == %d", "key", value as AnyObject) + let whereClause3 = Where("%K == %d", "key", NSNumber(value: value)) + let whereClause4 = Where("%K == %@", "key", value) + let whereClause5 = Where("%K == %@", "key", value as AnyObject) + let whereClause6 = Where("%K == %@", "key", NSNumber(value: value)) + XCTAssertEqual(whereClause1, whereClause2) + XCTAssertEqual(whereClause1, whereClause3) + XCTAssertEqual(whereClause1, whereClause4) + XCTAssertEqual(whereClause1, whereClause5) + XCTAssertEqual(whereClause1, whereClause6) + XCTAssertEqual(whereClause2, whereClause3) + XCTAssertEqual(whereClause2, whereClause4) + XCTAssertEqual(whereClause2, whereClause5) + XCTAssertEqual(whereClause2, whereClause6) + XCTAssertEqual(whereClause3, whereClause4) + XCTAssertEqual(whereClause3, whereClause5) + XCTAssertEqual(whereClause3, whereClause6) + XCTAssertEqual(whereClause4, whereClause5) + XCTAssertEqual(whereClause4, whereClause6) + XCTAssertEqual(whereClause5, whereClause6) + } + do { + + let value = NSNumber(value: 100) + let whereClause1 = Where("%K == %d", "key", value) + let whereClause2 = Where("%K == %d", "key", value as AnyObject) + let whereClause3 = Where("%K == %d", "key", value.intValue) + let whereClause4 = Where("%K == %@", "key", value) + let whereClause5 = Where("%K == %@", "key", value as AnyObject) + let whereClause6 = Where("%K == %@", "key", value.intValue) + XCTAssertEqual(whereClause1, whereClause2) + XCTAssertEqual(whereClause1, whereClause3) + XCTAssertEqual(whereClause1, whereClause4) + XCTAssertEqual(whereClause1, whereClause5) + XCTAssertEqual(whereClause1, whereClause6) + XCTAssertEqual(whereClause2, whereClause3) + XCTAssertEqual(whereClause2, whereClause4) + XCTAssertEqual(whereClause2, whereClause5) + XCTAssertEqual(whereClause2, whereClause6) + XCTAssertEqual(whereClause3, whereClause4) + XCTAssertEqual(whereClause3, whereClause5) + XCTAssertEqual(whereClause3, whereClause6) + XCTAssertEqual(whereClause4, whereClause5) + XCTAssertEqual(whereClause4, whereClause6) + XCTAssertEqual(whereClause5, whereClause6) + } + do { + + let value: Int64 = Int64.max + let whereClause1 = Where("%K == %d", "key", value) + let whereClause2 = Where("%K == %d", "key", value as AnyObject) + let whereClause3 = Where("%K == %d", "key", NSNumber(value: value)) + let whereClause4 = Where("%K == %@", "key", value) + let whereClause5 = Where("%K == %@", "key", value as AnyObject) + let whereClause6 = Where("%K == %@", "key", NSNumber(value: value)) + XCTAssertEqual(whereClause1, whereClause2) + XCTAssertEqual(whereClause1, whereClause3) + XCTAssertEqual(whereClause1, whereClause4) + XCTAssertEqual(whereClause1, whereClause5) + XCTAssertEqual(whereClause1, whereClause6) + XCTAssertEqual(whereClause2, whereClause3) + XCTAssertEqual(whereClause2, whereClause4) + XCTAssertEqual(whereClause2, whereClause5) + XCTAssertEqual(whereClause2, whereClause6) + XCTAssertEqual(whereClause3, whereClause4) + XCTAssertEqual(whereClause3, whereClause5) + XCTAssertEqual(whereClause3, whereClause6) + XCTAssertEqual(whereClause4, whereClause5) + XCTAssertEqual(whereClause4, whereClause6) + XCTAssertEqual(whereClause5, whereClause6) + } + do { + + let value = NSNumber(value: Int64.max) + let whereClause1 = Where("%K == %d", "key", value) + let whereClause2 = Where("%K == %d", "key", value as AnyObject) + let whereClause3 = Where("%K == %d", "key", value.int64Value) + let whereClause4 = Where("%K == %@", "key", value) + let whereClause5 = Where("%K == %@", "key", value as AnyObject) + let whereClause6 = Where("%K == %@", "key", value.int64Value) + XCTAssertEqual(whereClause1, whereClause2) + XCTAssertEqual(whereClause1, whereClause3) + XCTAssertEqual(whereClause1, whereClause4) + XCTAssertEqual(whereClause1, whereClause5) + XCTAssertEqual(whereClause1, whereClause6) + XCTAssertEqual(whereClause2, whereClause3) + XCTAssertEqual(whereClause2, whereClause4) + XCTAssertEqual(whereClause2, whereClause5) + XCTAssertEqual(whereClause2, whereClause6) + XCTAssertEqual(whereClause3, whereClause4) + XCTAssertEqual(whereClause3, whereClause5) + XCTAssertEqual(whereClause3, whereClause6) + XCTAssertEqual(whereClause4, whereClause5) + XCTAssertEqual(whereClause4, whereClause6) + XCTAssertEqual(whereClause5, whereClause6) + } + do { + + let value: String = "value" + let whereClause1 = Where("%K == %s", "key", value) + let whereClause2 = Where("%K == %s", "key", value as AnyObject) + let whereClause3 = Where("%K == %s", "key", NSString(string: value)) + let whereClause4 = Where("%K == %@", "key", value) + let whereClause5 = Where("%K == %@", "key", value as AnyObject) + let whereClause6 = Where("%K == %@", "key", NSString(string: value)) + XCTAssertEqual(whereClause1, whereClause2) + XCTAssertEqual(whereClause1, whereClause3) + XCTAssertEqual(whereClause1, whereClause4) + XCTAssertEqual(whereClause1, whereClause5) + XCTAssertEqual(whereClause1, whereClause6) + XCTAssertEqual(whereClause2, whereClause3) + XCTAssertEqual(whereClause2, whereClause4) + XCTAssertEqual(whereClause2, whereClause5) + XCTAssertEqual(whereClause2, whereClause6) + XCTAssertEqual(whereClause3, whereClause4) + XCTAssertEqual(whereClause3, whereClause5) + XCTAssertEqual(whereClause3, whereClause6) + XCTAssertEqual(whereClause4, whereClause5) + XCTAssertEqual(whereClause4, whereClause6) + XCTAssertEqual(whereClause5, whereClause6) + } + do { + + let value = NSString(string: "value") + let whereClause1 = Where("%K == %s", "key", value) + let whereClause2 = Where("%K == %s", "key", value as String) + let whereClause3 = Where("%K == %s", "key", value as String as AnyObject) + let whereClause4 = Where("%K == %@", "key", value) + let whereClause5 = Where("%K == %@", "key", value as String) + let whereClause6 = Where("%K == %@", "key", value as String as AnyObject) + XCTAssertEqual(whereClause1, whereClause2) + XCTAssertEqual(whereClause1, whereClause3) + XCTAssertEqual(whereClause1, whereClause4) + XCTAssertEqual(whereClause1, whereClause5) + XCTAssertEqual(whereClause1, whereClause6) + XCTAssertEqual(whereClause2, whereClause3) + XCTAssertEqual(whereClause2, whereClause4) + XCTAssertEqual(whereClause2, whereClause5) + XCTAssertEqual(whereClause2, whereClause6) + XCTAssertEqual(whereClause3, whereClause4) + XCTAssertEqual(whereClause3, whereClause5) + XCTAssertEqual(whereClause3, whereClause6) + XCTAssertEqual(whereClause4, whereClause5) + XCTAssertEqual(whereClause4, whereClause6) + XCTAssertEqual(whereClause5, whereClause6) + } + do { + + let value: [Int] = [100, 200] + let whereClause1 = Where("%K == %@", "key", value) + let whereClause2 = Where("%K == %@", "key", value as AnyObject) + let whereClause3 = Where("%K == %@", "key", value as [AnyObject]) + let whereClause4 = Where("%K == %@", "key", value as NSArray) + let whereClause5 = Where("%K == %@", "key", NSArray(array: value)) + let whereClause6 = Where("%K == %@", "key", value as AnyObject as! NSArray) + XCTAssertEqual(whereClause1, whereClause2) + XCTAssertEqual(whereClause1, whereClause3) + XCTAssertEqual(whereClause1, whereClause4) + XCTAssertEqual(whereClause1, whereClause5) + XCTAssertEqual(whereClause1, whereClause6) + XCTAssertEqual(whereClause2, whereClause3) + XCTAssertEqual(whereClause2, whereClause4) + XCTAssertEqual(whereClause2, whereClause5) + XCTAssertEqual(whereClause2, whereClause6) + XCTAssertEqual(whereClause3, whereClause4) + XCTAssertEqual(whereClause3, whereClause5) + XCTAssertEqual(whereClause3, whereClause6) + XCTAssertEqual(whereClause4, whereClause5) + XCTAssertEqual(whereClause4, whereClause6) + XCTAssertEqual(whereClause5, whereClause6) + } + do { + + let value: [Int64] = [Int64.min, 100, Int64.max] + let whereClause1 = Where("%K == %@", "key", value) + let whereClause2 = Where("%K == %@", "key", value as AnyObject) + let whereClause3 = Where("%K == %@", "key", value as [AnyObject]) + let whereClause4 = Where("%K == %@", "key", value as NSArray) + let whereClause5 = Where("%K == %@", "key", NSArray(array: value)) + let whereClause6 = Where("%K == %@", "key", value as AnyObject as! NSArray) + XCTAssertEqual(whereClause1, whereClause2) + XCTAssertEqual(whereClause1, whereClause3) + XCTAssertEqual(whereClause1, whereClause4) + XCTAssertEqual(whereClause1, whereClause5) + XCTAssertEqual(whereClause1, whereClause6) + XCTAssertEqual(whereClause2, whereClause3) + XCTAssertEqual(whereClause2, whereClause4) + XCTAssertEqual(whereClause2, whereClause5) + XCTAssertEqual(whereClause2, whereClause6) + XCTAssertEqual(whereClause3, whereClause4) + XCTAssertEqual(whereClause3, whereClause5) + XCTAssertEqual(whereClause3, whereClause6) + XCTAssertEqual(whereClause4, whereClause5) + XCTAssertEqual(whereClause4, whereClause6) + XCTAssertEqual(whereClause5, whereClause6) + } + } + @objc dynamic func test_ThatWhereClauseOperations_ComputeCorrectly() { @@ -98,7 +303,7 @@ final class WhereTests: XCTestCase { let notWhere = !whereClause1 let notPredicate = NSCompoundPredicate( - type: .NotPredicateType, + type: .not, subpredicates: [whereClause1.predicate] ) XCTAssertEqual(notWhere.predicate, notPredicate) @@ -108,10 +313,10 @@ final class WhereTests: XCTestCase { let andWhere = whereClause1 && whereClause2 && whereClause3 let andPredicate = NSCompoundPredicate( - type: .AndPredicateType, + type: .and, subpredicates: [ NSCompoundPredicate( - type: .AndPredicateType, + type: .and, subpredicates: [whereClause1.predicate, whereClause2.predicate] ), whereClause3.predicate @@ -124,10 +329,10 @@ final class WhereTests: XCTestCase { let orWhere = whereClause1 || whereClause2 || whereClause3 let orPredicate = NSCompoundPredicate( - type: .OrPredicateType, + type: .or, subpredicates: [ NSCompoundPredicate( - type: .OrPredicateType, + type: .or, subpredicates: [whereClause1.predicate, whereClause2.predicate] ), whereClause3.predicate diff --git a/Package.swift b/Package.swift index 0ab361a..0680db5 100644 --- a/Package.swift +++ b/Package.swift @@ -41,11 +41,5 @@ targets = [] let package = Package( name: "CoreStore", targets: targets, - dependencies: [ - .Package( - url: "https://github.com/JohnEstropia/GCDKit.git", - "1.2.6" - ) - ], exclude: ["Carthage", "CoreStoreDemo", "Sources/libA/images"] ) diff --git a/README.md b/README.md index 114485a..8e42191 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,11 @@ Unleashing the real power of Core Data with the elegance and safety of Swift

-* iOS 7+ / macOS 10.10+ / watchOS 2.0+ / tvOS 9.0+ - - for Swift 2.2 (Xcode 7.3 and iOS 7): Use version [2.0.6](https://github.com/JohnEstropia/CoreStore/releases/tag/2.0.6) or the [master_ios_7_to_9](https://github.com/JohnEstropia/CoreStore/tree/master_ios_7_to_9) branch - - for Swift 2.3 (Xcode 8): Use version [2.1.0](https://github.com/JohnEstropia/CoreStore/releases/tag/2.1.0) or the [master](https://github.com/JohnEstropia/CoreStore/tree/master) branch - - for Swift 3 (Xcode 8): Use the [swift3_develop](https://github.com/JohnEstropia/CoreStore/tree/swift3_develop) branch +* **Swift 3.0.1:** iOS 8+ / macOS 10.10+ / watchOS 2.0+ / tvOS 9.0+ * **New in CoreStore 2.0:** Objective-C support! All CoreStore types now have their corresponding Objective-C "bridging classes". Perfect for projects transitioning from Objective-C to Swift! -Upgrading from CoreStore 1.x to 2.x? Check out the [new features](#new-in-corestore-20) and make sure to read the [Migration guide](#upgrading-from-1xx-to-2xx). +Upgrading from CoreStore 2.x to 3.x? Check out the [new features](#new-in-corestore-20) and make sure to read the [Migration guide](#upgrading-from-2xx-to-3xx). ## Why use CoreStore? @@ -44,12 +41,10 @@ CoreStore was (and is) heavily shaped by real-world needs of developing data-dep - **Efficient importing utilities.** Map your entities once with their corresponding import source (JSON for example), and importing from *transactions* becomes elegant. Uniquing is also done with an efficient find-and-replace algorithm. *(See [Importing data](#importing-data))* - **Tight design around Swift’s code elegance and type safety.** CoreStore fully utilizes Swift's community-driven language features. - **Full 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 CoreStore 2.0 - **Informative (and pretty) logs.** All CoreStore and Core Data-related types now have very informative and pretty print outputs! *(See [Logging and error reporting](#logging-and-error-reporting))* -- **Objective-C support!** Is your project transitioning from Objective-C to Swift but still can't quite fully convert some huge classes to Swift yet? CoreStore 2.0 is the answer to the ever-increasing Swift adoption. While still written in pure Swift, all CoreStore types now have their corresponding Objective-C-visible "bridging classes". *(See [Objective-C support](#objective-c-support))* -- **iCloud storage (beta) support.** CoreStore now allows creation of iCloud persistent stores, as well as observing of iCloud-related events through the `ICloudStoreObserver`. *(See [iCloud storage](#icloud-storages))* -- **More extensive Unit Tests.** Extending CoreStore is now safer without having to worry about breaking old behavior. +- **Objective-C support!** Is your project transitioning from Objective-C to Swift but still can't quite fully convert some huge classes to Swift yet? CoreStore adjusts to the ever-increasing Swift adoption. While still written in pure Swift, all CoreStore types have their corresponding Objective-C-visible "bridging classes". *(See [Objective-C support](#objective-c-support))* +- **iCloud storage (beta) support.** CoreStore allows creation of iCloud persistent stores, as well as observing of iCloud-related events through the `ICloudStoreObserver`. *(See [iCloud storage](#icloud-storages))* +- **More extensive Unit Tests.** Extending CoreStore is safe without having to worry about breaking old behavior. *Have ideas that may benefit other Core Data users? [Feature Request](https://github.com/JohnEstropia/CoreStore/issues)s are welcome!* @@ -92,6 +87,7 @@ CoreStore was (and is) heavily shaped by real-world needs of developing data-dep - [Roadmap](#roadmap) - [Installation](#installation) - [Changesets](#changesets) + - [Upgrading from 2.x.x to 3.x.x](#upgrading-from-2xx-to-3xx) - [Upgrading from 1.x.x to 2.x.x](#upgrading-from-1xx-to-2xx) - [Contact](#contact) - [Who uses CoreStore?](#who-uses-corestore) @@ -122,14 +118,14 @@ CoreStore.addStorage( Starting transactions: ```swift CoreStore.beginAsynchronous { (transaction) -> Void in - let person = transaction.create(Into(MyPersonEntity)) + let person = transaction.create(Into()) person.name = "John Smith" person.age = 42 transaction.commit { (result) -> Void in switch result { - case .Success(let hasChanges): print("success!") - case .Failure(let error): print(error) + case .success(let hasChanges): print("success!") + case .failure(let error): print(error) } } } @@ -137,15 +133,15 @@ CoreStore.beginAsynchronous { (transaction) -> Void in Fetching objects (simple): ```swift -let people = CoreStore.fetchAll(From(MyPersonEntity)) +let people = CoreStore.fetchAll(From()) ``` Fetching objects (complex): ```swift let people = CoreStore.fetchAll( - From(MyPersonEntity), + From(), Where("age > 30"), - OrderBy(.Ascending("name"), .Descending("age")), + OrderBy(.ascending("name"), .descending("age")), Tweak { (fetchRequest) -> Void in fetchRequest.includesPendingChanges = false } @@ -155,8 +151,8 @@ let people = CoreStore.fetchAll( Querying values: ```swift let maxAge = CoreStore.queryValue( - From(MyPersonEntity), - Select(.Maximum("age")) + From(), + Select(.maximum("age")) ) ``` @@ -210,13 +206,13 @@ let migrationProgress = dataStack.addStorage( SQLiteStore( fileURL: sqliteFileURL, // set the target file URL for the sqlite file configuration: "Config2", // use entities from the "Config2" configuration in the .xcdatamodeld file - localStorageOptions: .RecreateStoreOnModelMismatch // if migration paths cannot be resolved, recreate the sqlite file + localStorageOptions: .recreateStoreOnModelMismatch // if migration paths cannot be resolved, recreate the sqlite file ), completion: { (result) -> Void in switch result { - case .Success(let storage): + case .success(let storage): print("Successfully added sqlite store: \(storage)" - case .Failure(let error): + case .failure(let error): print("Failed adding sqlite store with error: \(error)" } } @@ -235,7 +231,7 @@ class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() do { - try self.dataStack.addStorageAndWait(SQLiteStore) + try self.dataStack.addStorageAndWait(SQLiteStore.self) } catch { // ... } @@ -253,7 +249,7 @@ class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() do { - try CoreStore.addStorageAndWait(SQLiteStore) + try CoreStore.addStorageAndWait(SQLiteStore.self) } catch { // ... } @@ -278,7 +274,7 @@ try CoreStore.addStorageAndWait( ``` `InMemoryStore`s also implement the `DefaultInitializableStore` sugar protocol which tells CoreStore that this store can initialize without any arguments (`init()`). This lets us provide just the type instead of an instance: ```swift -try CoreStore.addStorageAndWait(InMemoryStore) +try CoreStore.addStorageAndWait(InMemoryStore.self) ``` ### Local Store @@ -289,7 +285,7 @@ let migrationProgress = CoreStore.addStorage( fileName: "MyStore.sqlite", configuration: "Config2", // optional. Use entities from the "Config2" configuration in the .xcdatamodeld file mappingModelBundles: [NSBundle.mainBundle()], // optional. The bundles that contain required .xcmappingmodel files, if any - localStorageOptions: .RecreateStoreOnModelMismatch // optional. Provides settings that tells the DataStack how to setup the persistent store + localStorageOptions: .recreateStoreOnModelMismatch // optional. Provides settings that tells the DataStack how to setup the persistent store ), completion: { /* ... */ } ) @@ -298,7 +294,7 @@ Refer to the *SQLiteStore.swift* source documentation for detailed explanations CoreStore can decide the default values for these properties, so `SQLiteStore`s also implement the `DefaultInitializableStore` sugar protocol which lets us write: ```swift -try CoreStore.addStorageAndWait(SQLiteStore) +try CoreStore.addStorageAndWait(SQLiteStore.self) ``` or ```swift @@ -311,8 +307,8 @@ public protocol LocalStorage: StorageInterface { var fileURL: NSURL { get } var mappingModelBundles: [NSBundle] { get } var localStorageOptions: LocalStorageOptions { get } - func storeOptionsForOptions(options: LocalStorageOptions) -> [String: AnyObject]? - func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel?) throws + func dictionary(forOptions: LocalStorageOptions) -> [String: AnyObject]? + func eraseStorageAndWait(metadata: [String: Any], soureModelHint: NSManagedObjectModel?) throws } ``` If you have custom `NSIncrementalStore` or `NSAtomicStore` subclasses, you can implement this protocol and use it similarly to `SQLiteStore`. @@ -328,7 +324,7 @@ guard let storage = ICloudStore( ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername", // optional. The container if your app has multiple ubiquity container identifiers in its entitlements ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0", // optional. A per-application salt to allow multiple apps on the same device to share a Core Data store integrated with iCloud configuration: "Config1", // optional. Use entities from the "Config1" configuration in the .xcdatamodeld file - cloudStorageOptions: .RecreateLocalStoreOnModelMismatch // optional. Provides settings that tells the DataStack how to setup the persistent store + cloudStorageOptions: .recreateLocalStoreOnModelMismatch // optional. Provides settings that tells the DataStack how to setup the persistent store ) else { // The iCloud container could not be located or if iCloud is not available on the device. // Handle appropriately @@ -338,8 +334,8 @@ CoreStore.addStorage(, storage, completion: { result in switch result { - case .Success(let storage): // ... - case .Failure(let error): // ... + case .success(let storage): // ... + case .failure(let error): // ... } } ) @@ -369,8 +365,8 @@ CoreStore.addStorage(, storage, completion: { result in switch result { - case .Success(let storage): // ... You may also call storage.addObserver(_:) here - case .Failure(let error): // ... + case .success(let storage): // ... You may also call storage.addObserver(_:) here + case .failure(let error): // ... } } ) @@ -379,12 +375,12 @@ The `ICloudStore` only keeps weak references of the registered observers. You ma ## Migrations -We have seen `addStorageAndWait(...)` used to initialize our persistent store. As the method name's "AndWait" suffix suggests though, this method blocks so it should not do long tasks such as store migrations. In fact CoreStore will only attempt a synchronous **lightweight** migration if you explicitly provide the `.AllowSynchronousLightweightMigration` option: +We have seen `addStorageAndWait(...)` used to initialize our persistent store. As the method name's "AndWait" suffix suggests though, this method blocks so it should not do long tasks such as store migrations. In fact CoreStore will only attempt a synchronous **lightweight** migration if you explicitly provide the `.allowSynchronousLightweightMigration` option: ```swift try dataStack.addStorageAndWait( SQLiteStore( fileURL: sqliteFileURL, - localStorageOptions: .AllowSynchronousLightweightMigration + localStorageOptions: .allowSynchronousLightweightMigration ) } ``` @@ -392,16 +388,16 @@ if you do so, any model mismatch will be thrown as an error. In general though, if migrations are expected the asynchronous variant `addStorage(_:completion:)` method is recommended instead: ```swift -let migrationProgress: NSProgress? = try dataStack.addStorage( +let migrationProgress: Progress? = try dataStack.addStorage( SQLiteStore( fileName: "MyStore.sqlite", configuration: "Config2" ), completion: { (result) -> Void in switch result { - case .Success(let storage): + case .success(let storage): print("Successfully added sqlite store: \(storage)") - case .Failure(let error): + case .failure(let error): print("Failed adding sqlite store with error: \(error)") } } @@ -409,7 +405,7 @@ let migrationProgress: NSProgress? = try dataStack.addStorage( ``` The `completion` block reports a `SetupResult` that indicates success or failure. -Notice that this method also returns an optional `NSProgress`. If `nil`, no migrations are needed, thus progress reporting is unnecessary as well. If not `nil`, you can use this to track migration progress by using standard KVO on the `"fractionCompleted"` key, or by using a closure-based utility exposed in *NSProgress+Convenience.swift*: +Notice that this method also returns an optional `Progress`. If `nil`, no migrations are needed, thus progress reporting is unnecessary as well. If not `nil`, you can use this to track migration progress by using standard KVO on the `"fractionCompleted"` key, or by using a closure-based utility exposed in *Progress+Convenience.swift*: ```swift migrationProgress?.setProgressHandler { [weak self] (progress) -> Void in self?.progressView?.setProgress(Float(progress.fractionCompleted), animated: true) @@ -559,7 +555,7 @@ You've seen how to create transactions, but we have yet to see how to make *crea The `create(...)` method accepts an `Into` clause which specifies the entity for the object you want to create: ```swift -let person = transaction.create(Into(MyPersonEntity)) +let person = transaction.create(Into()) ``` While the syntax is straightforward, CoreStore does not just naively insert a new object. This single line does the following: - Checks that the entity type exists in any of the transaction's parent persistent store @@ -582,7 +578,7 @@ Note that if you do explicitly specify the configuration name, CoreStore will on After creating an object from the transaction, you can simply update its properties as normal: ```swift CoreStore.beginAsynchronous { (transaction) -> Void in - let person = transaction.create(Into(MyPersonEntity)) + let person = transaction.create(Into()) person.name = "John Smith" person.age = 30 transaction.commit() @@ -592,7 +588,7 @@ To update an existing object, fetch the object's instance from the transaction: ```swift CoreStore.beginAsynchronous { (transaction) -> Void in let person = transaction.fetchOne( - From(MyPersonEntity), + From(), Where("name", isEqualTo: "Jane Smith") ) person.age = person.age + 1 @@ -654,7 +650,7 @@ If you do not have references yet to the objects to be deleted, transactions hav ```swift CoreStore.beginAsynchronous { (transaction) -> Void in transaction.deleteAll( - From(MyPersonEntity) + From(), Where("age > 30") ) transaction.commit() @@ -692,7 +688,7 @@ var peopleIDs: [NSManagedObjectID] = // ... CoreStore.beginAsynchronous { (transaction) -> Void in let jane = transaction.fetchOne( - From(MyPersonEntity), + From(), Where("name", isEqualTo: "Jane Smith") ) jane.friends = NSSet(array: transaction.fetchExisting(peopleIDs)!) @@ -714,7 +710,7 @@ If you have many attributes, you don't want to keep repeating this mapping every CoreStore.beginAsynchronous { (transaction) -> Void in let json: [String: AnyObject] = // ... try! transaction.importObject( - Into(MyPersonEntity), + Into(), source: json ) transaction.commit() @@ -741,8 +737,8 @@ You can even use external types from popular 3rd-party JSON libraries ([SwiftyJS ```swift public protocol ImportableObject: class { typealias ImportSource - static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool - func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws + static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool + func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws } ``` First, set `ImportSource` to the expected type of the data source: @@ -754,15 +750,15 @@ This lets us call `importObject(_:source:)` with any `[String: AnyObject]` type CoreStore.beginAsynchronous { (transaction) -> Void in let json: [String: AnyObject] = // ... try! transaction.importObject( - Into(MyPersonEntity), + Into(), source: json ) // ... } ``` -The actual extraction and assignment of values should be implemented in the `didInsertFromImportSource(...)` method of the `ImportableObject` protocol: +The actual extraction and assignment of values should be implemented in the `didInsert(from:in:)` method of the `ImportableObject` protocol: ```swift -func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { +func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws { self.name = source["name"] as? NSString self.age = source["age"] as? NSNumber // ... @@ -773,17 +769,17 @@ Transactions also let you import multiple objects at once using the `importObjec CoreStore.beginAsynchronous { (transaction) -> Void in let jsonArray: [[String: AnyObject]] = // ... try! transaction.importObjects( - Into(MyPersonEntity), + Into(), 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. +Doing so tells the transaction to iterate through the array of import sources and calls `shouldInsert(from:in:)` on the `ImportableObject` to determine which instances should be created. You can do validations and return `false` from `shouldInsert(from:in:)` 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(...)`: +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 `didInsert(from:in:)`: ```swift -func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws { +func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws { self.name = source["name"] as? NSString self.age = source["age"] as? NSNumber // ... @@ -798,7 +794,7 @@ CoreStore.beginAsynchronous { (transaction) -> Void in let jsonArray: [[String: AnyObject]] = // ... do { try transaction.importObjects( - Into(MyPersonEntity), + Into(), sourceArray: jsonArray ) } @@ -821,11 +817,11 @@ public protocol ImportableUniqueObject: ImportableObject { 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 + static func shouldInsert(from source: ImportSource, inn transaction: BaseDataTransaction) -> Bool + static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool + static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> UniqueIDType? + func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws + func update(from source: ImportSource, in transaction: BaseDataTransaction) throws } ``` Notice that it has the same insert methods as `ImportableObject`, with additional methods for updates and for specifying the unique ID: @@ -837,18 +833,18 @@ var uniqueIDValue: NSNumber { get { return self.personID } set { self.personID = newValue } } -class func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> NSNumber? { +class func uniqueID(from source: ImportSource, in 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. +For `ImportableUniqueObject`, the extraction and assignment of values should be implemented from the `update(from:in:)` method. The `didInsert(from:in:)` by default calls `update(from:in:)`, but you can separate the implementation for inserts and updates if needed. You can then 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), + Into(), source: json ) // ... @@ -860,14 +856,14 @@ or multiple objects at once with the `importUniqueObjects(...)` method: CoreStore.beginAsynchronous { (transaction) -> Void in let jsonArray: [[String: AnyObject]] = // ... try! transaction.importUniqueObjects( - Into(MyPersonEntity), + Into(), 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. +`shouldInsert(from:in:)` and `shouldUpdate(from:in:)`, or to cancel all objects by `throw`ing an error from the `uniqueID(from:in:)`, `didInsert(from:in:)` or `update(from:in:)` methods. ## Fetching and Querying @@ -884,10 +880,10 @@ Before we dive in, be aware that CoreStore distinguishes between *fetching* and #### `From` clause The search conditions for fetches and queries are specified using *clauses*. All fetches and queries require a `From` clause that indicates the target entity type: ```swift -let people = CoreStore.fetchAll(From(MyPersonEntity)) +let people = CoreStore.fetchAll(From()) // CoreStore.fetchAll(From()) works as well ``` -`people` in the example above will be of type `[MyPersonEntity]`. The `From(MyPersonEntity)` clause indicates a fetch to all persistent stores that `MyPersonEntity` belong to. +`people` in the example above will be of type `[MyPersonEntity]`. The `From()` clause indicates a fetch to all persistent stores that `MyPersonEntity` belong to. If the entity exists in multiple configurations and you need to only search from a particular configuration, indicate in the `From` clause the configuration name for the destination persistent store: ```swift @@ -916,11 +912,11 @@ Each method's purpose is straightforward, but we need to understand how to set t The `Where` clause is CoreStore's `NSPredicate` wrapper. It specifies the search filter to use when fetching (or querying). It implements all initializers that `NSPredicate` does (except for `-predicateWithBlock:`, which Core Data does not support): ```swift var people = CoreStore.fetchAll( - From(MyPersonEntity), + From(), Where("%K > %d", "age", 30) // string format initializer ) people = CoreStore.fetchAll( - From(MyPersonEntity), + From(), Where(true) // boolean initializer ) ``` @@ -928,14 +924,14 @@ If you do have an existing `NSPredicate` instance already, you can pass that to ```swift let predicate = NSPredicate(...) var people = CoreStore.fetchAll( - From(MyPersonEntity), + From(), Where(predicate) // predicate initializer ) ``` `Where` clauses also implement the `&&`, `||`, and `!` logic operators, so you can provide logical conditions without writing too much `AND`, `OR`, and `NOT` strings: ```swift var people = CoreStore.fetchAll( - From(MyPersonEntity), + From(), Where("age > %d", 30) && Where("gender == %@", "M") ) ``` @@ -946,20 +942,20 @@ If you do not provide a `Where` clause, all objects that belong to the specified The `OrderBy` clause is CoreStore's `NSSortDescriptor` wrapper. Use it to specify attribute keys in which to sort the fetch (or query) results with. ```swift var mostValuablePeople = CoreStore.fetchAll( - From(MyPersonEntity), - OrderBy(.Descending("rating"), .Ascending("surname")) + From(), + OrderBy(.descending("rating"), .ascending("surname")) ) ``` -As seen above, `OrderBy` accepts a list of `SortKey` enumeration values, which can be either `.Ascending` or `.Descending`. +As seen above, `OrderBy` accepts a list of `SortKey` enumeration values, which can be either `.ascending` or `.descending`. You can use the `+` and `+=` operator to append `OrderBy`s together. This is useful when sorting conditionally: ```swift -var orderBy = OrderBy(.Descending("rating")) +var orderBy = OrderBy(.descending("rating")) if sortFromYoungest { - orderBy += OrderBy(.Ascending("age")) + orderBy += OrderBy(.ascending("age")) } var mostValuablePeople = CoreStore.fetchAll( - From(MyPersonEntity), + From(), orderBy ) ``` @@ -969,9 +965,9 @@ var mostValuablePeople = CoreStore.fetchAll( The `Tweak` clause lets you, uh, *tweak* the fetch (or query). `Tweak` exposes the `NSFetchRequest` in a closure where you can make changes to its properties: ```swift var people = CoreStore.fetchAll( - From(MyPersonEntity), + From(), Where("age > %d", 30), - OrderBy(.Ascending("surname")), + OrderBy(.ascending("surname")), Tweak { (fetchRequest) -> Void in fetchRequest.includesPendingChanges = false fetchRequest.returnsObjectsAsFaults = false @@ -1000,7 +996,7 @@ Setting up the `From`, `Where`, `OrderBy`, and `Tweak` clauses is similar to how The `Select` clause specifies the target attribute/aggregate key, as well as the expected return type: ```swift let johnsAge = CoreStore.queryValue( - From(MyPersonEntity), + From(), Select("age"), Where("name == %@", "John Smith") ) @@ -1025,29 +1021,29 @@ The example above queries the "age" property for the first object that matches t For `queryAttributes(...)`, only `NSDictionary` is valid for `Select`, thus you are allowed to omit the generic type: ```swift let allAges = CoreStore.queryAttributes( - From(MyPersonEntity), + From(), Select("age") ) ``` If you only need a value for a particular attribute, you can just specify the key name (like we did with `Select("age")`), but several aggregate functions can also be used as parameter to `Select`: -- `.Average(...)` -- `.Count(...)` -- `.Maximum(...)` -- `.Minimum(...)` -- `.Sum(...)` +- `.average(...)` +- `.count(...)` +- `.maximum(...)` +- `.minimum(...)` +- `.sum(...)` ```swift let oldestAge = CoreStore.queryValue( - From(MyPersonEntity), - Select(.Maximum("age")) + From(), + Select(.maximum("age")) ) ``` For `queryAttributes(...)` which returns an array of dictionaries, you can specify multiple attributes/aggregates to `Select`: ```swift let personJSON = CoreStore.queryAttributes( - From(MyPersonEntity), + From(), Select("name", "age") ) ``` @@ -1067,8 +1063,8 @@ let personJSON = CoreStore.queryAttributes( You can also include an aggregate as well: ```swift let personJSON = CoreStore.queryAttributes( - From(MyPersonEntity), - Select("name", .Count("friends")) + From(), + Select("name", .count("friends")) ) ``` which returns: @@ -1087,8 +1083,8 @@ which returns: The `"count(friends)"` key name was automatically used by CoreStore, but you can specify your own key alias if you need: ```swift let personJSON = CoreStore.queryAttributes( - From(MyPersonEntity), - Select("name", .Count("friends", As: "friendsCount")) + From(), + Select("name", .count("friends", as: "friendsCount")) ) ``` which now returns: @@ -1110,8 +1106,8 @@ which now returns: The `GroupBy` clause lets you group results by a specified attribute/aggregate. This is useful only for `queryAttributes(...)` since `queryValue(...)` just returns the first value. ```swift let personJSON = CoreStore.queryAttributes( - From(MyPersonEntity), - Select("age", .Count("age", As: "count")), + From(), + Select("age", .count("age", as: "count")), GroupBy("age") ) ``` @@ -1157,7 +1153,7 @@ A couple of examples, `ListMonitor`: screen shot 2016-07-10 at 22 56 44 -`CoreStoreError.MappingModelNotFoundError`: +`CoreStoreError.mappingModelNotFoundError`: MappingModelNotFoundError @@ -1236,9 +1232,9 @@ Including `ListObserver`, there are 3 observer protocols you can implement depen We then need to create a `ListMonitor` instance and register our `ListObserver` as an observer: ```swift self.monitor = CoreStore.monitorList( - From(MyPersonEntity), + From(), Where("age > 30"), - OrderBy(.Ascending("name")), + OrderBy(.ascending("name")), Tweak { (fetchRequest) -> Void in fetchRequest.fetchBatchSize = 20 } @@ -1257,10 +1253,10 @@ let firstPerson = self.monitor[0] If the list needs to be grouped into sections, create the `ListMonitor` instance with the `monitorSectionedList(...)` method and a `SectionBy` clause: ```swift self.monitor = CoreStore.monitorSectionedList( - From(MyPersonEntity), + From(), SectionBy("age"), Where("gender", isEqualTo: "M"), - OrderBy(.Ascending("age"), .Ascending("name")), + OrderBy(.ascending("age"), .ascending("name")), Tweak { (fetchRequest) -> Void in fetchRequest.fetchBatchSize = 20 } @@ -1271,11 +1267,11 @@ A list controller created this way will group the objects by the attribute key i The `SectionBy` clause can also be passed a closure to transform the section name into a displayable string: ```swift self.monitor = CoreStore.monitorSectionedList( - From(MyPersonEntity), + From(), SectionBy("age") { (sectionName) -> String? in "\(sectionName) years old" }, - OrderBy(.Ascending("age"), .Ascending("name")) + OrderBy(.ascending("age"), .ascending("name")) ) ``` This is useful when implementing a `UITableViewDelegate`'s section header: @@ -1304,7 +1300,7 @@ With 2.0, all CoreStore types are still written in pure Swift, but they now have SwiftObjective-C
-try CoreStore.addStorageAndWait(SQLiteStore)
+try CoreStore.addStorageAndWait(SQLiteStore.self)
 
 NSError *error
@@ -1317,8 +1313,8 @@ CoreStore.beginAsynchronous { (transaction) in
     // ...
     transaction.commit { (result) in
         switch result {
-        case .Success(let hasChanges): print(hasChanges)
-        case .Failure(let error): print(error)
+        case .success(let hasChanges): print(hasChanges)
+        case .failure(let error): print(error)
         }
     }
 }
@@ -1428,9 +1424,9 @@ To use these syntax sugars, include *CoreStoreBridge.h* in your Objective-C sour
 # Installation
 - Requires:
     - iOS 8 SDK and above
-    - Swift 2.3 (Xcode 8)
+    - Swift 3.0.1 (Xcode 8.2)
 - Dependencies:
-    - [GCDKit](https://github.com/JohnEstropia/GCDKit)
+    - *None*
 - Other notes:
     - The `com.apple.CoreData.ConcurrencyDebug` debug argument should be turned off for the app. CoreStore already guarantees safety for you by making the main context read-only, and by only executing transactions serially.
 
@@ -1443,8 +1439,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift
 ### Install with Carthage
 In your `Cartfile`, add
 ```
-github "JohnEstropia/CoreStore" >= 2.1.0
-github "JohnEstropia/GCDKit" >= 1.3.0
+github "JohnEstropia/CoreStore" >= 3.0.0
 ```
 and run 
 ```
@@ -1469,6 +1464,29 @@ Add all *.swift* files to your project.
 To use the Objective-C syntax sugars, import *CoreStoreBridge.h* in your *.m* source files.
 
 # Changesets
+### Upgrading from 2.x.x to 3.x.x
+**Obsoleted**
+- `UnsageDataTransaction.internalContext` was removed. Accessing the internal context (or more specifically, accessing context-level methods such as fetches) are now available through the `FetchableSource` and `QueryableProtocol` protocols, which are retrievable with `NSManagedObject.fetchSource()` and `NSManagedObject.querySource()` respectively. These protocols are implemented by `DataStack` and `BaseDataTransaction`.
+
+**Deprecated**
+Methods have been renamed to better fit the [Swift 3 naming conventions](https://swift.org/documentation/api-design-guidelines/).
+- `entityDescriptionForType(_:)` → `entityDescription(for:)`
+- `objectIDForURIRepresentation(_:)` → `objectID(for:)`
+- `ImportableObject` and `ImportableUniqueObject` protocol methods (and their variants) have been renamed. The old methods are still available, but will be removed in a future update.
+    - `shouldInsertFromImportSource(_:inTransaction:)` → `shouldInsert(from:in:)`
+    - `didInsertFromImportSource(_:inTransaction:)` → `didInsert(from:in:)`
+    - `shouldUpdateFromImportSource(_:inTransaction :)` → `shouldUpdate(from:in:)`
+    - `uniqueIDFromImportSource(_:inTransaction :)` → `uniqueID(from:in:)`
+    - `updateFromImportSource(_:inTransaction:)` → `update(from:in:)`
+
+**Miscellaneous**
+- APIs obsoleted from 2.0.0 have been removed.
+- CoreStore does not depend on [GCDKit](https://github.com/JohnEstropia/GCDKit) anymore, thanks to Swift 3's better Grand Central Dispatch API.
+- All enum cases are now lowercased
+- `CoreStoreError` now implements the new Swift `CustomNSError` protocol for better Objective-C 
+bridging.
+- Some methods may emit warnings for unused return values. `@discardableResult` annotations have been set to better reflect the responsibility of API users to use/inspect return values.
+
 ### Upgrading from 1.x.x to 2.x.x
 **Obsoleted**
 - `AsynchronousDataTransaction.rollback()` was removed. Undo and rollback functionality are now only allowed on `UnsafeDataTransaction`s
diff --git a/Sources/Convenience/NSFetchedResultsController+Convenience.swift b/Sources/Convenience/NSFetchedResultsController+Convenience.swift
index ec8b223..56d0e37 100644
--- a/Sources/Convenience/NSFetchedResultsController+Convenience.swift
+++ b/Sources/Convenience/NSFetchedResultsController+Convenience.swift
@@ -26,28 +26,26 @@
 import Foundation
 import CoreData
 
-
 #if os(iOS) || os(watchOS) || os(tvOS)
 
-// MARK: - NSFetchedResultsController
+// MARK: - DataStack
 
-public extension NSFetchedResultsController {
+public extension DataStack {
     
     /**
-     Utility for creating an `NSFetchedResultsController` from a `DataStack`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     Utility for creating an `NSFetchedResultsController` from the `DataStack`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `performFetch()` on the created `NSFetchedResultsController`.
      
-     - parameter dataStack: the `DataStack` to observe objects from
      - parameter from: a `From` clause indicating the entity type
      - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
-     - returns: an `NSFetchedResultsController` that observes a `DataStack`
+     - returns: an `NSFetchedResultsController` that observes the `DataStack`
      */
     @nonobjc
-    public static func createFor(dataStack: DataStack, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> NSFetchedResultsController {
+    public func createFetchedResultsController(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> NSFetchedResultsController {
         
-        return self.createFromContext(
-            dataStack.mainContext,
-            fetchRequest: CoreStoreFetchRequest(),
+        return createFRC(
+            fromContext: self.mainContext,
             from: from,
             sectionBy: sectionBy,
             fetchClauses: fetchClauses
@@ -56,19 +54,18 @@ public extension NSFetchedResultsController {
     
     /**
      Utility for creating an `NSFetchedResultsController` from a `DataStack`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `performFetch()` on the created `NSFetchedResultsController`.
      
-     - parameter dataStack: the `DataStack` to observe objects from
      - parameter from: a `From` clause indicating the entity type
      - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
-     - returns: an `NSFetchedResultsController` that observes a `DataStack`
+     - returns: an `NSFetchedResultsController` that observes the `DataStack`
      */
     @nonobjc
-    public static func createFor(dataStack: DataStack, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController {
+    public func createFetchedResultsController(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController {
         
-        return self.createFromContext(
-            dataStack.mainContext,
-            fetchRequest: CoreStoreFetchRequest(),
+        return createFRC(
+            fromContext: self.mainContext,
             from: from,
             sectionBy: sectionBy,
             fetchClauses: fetchClauses
@@ -76,19 +73,18 @@ public extension NSFetchedResultsController {
     }
     
     /**
-     Utility for creating an `NSFetchedResultsController` from a `DataStack`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     Utility for creating an `NSFetchedResultsController` from the `DataStack`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `performFetch()` on the created `NSFetchedResultsController`.
      
-     - parameter dataStack: the `DataStack` to observe objects from
      - 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: an `NSFetchedResultsController` that observes a `DataStack`
+     - returns: an `NSFetchedResultsController` that observes the `DataStack`
      */
     @nonobjc
-    public static func createFor(dataStack: DataStack, _ from: From, _ fetchClauses: FetchClause...) -> NSFetchedResultsController {
+    public func createFetchedResultsController(_ from: From, _ fetchClauses: FetchClause...) -> NSFetchedResultsController {
         
-        return self.createFromContext(
-            dataStack.mainContext,
-            fetchRequest: CoreStoreFetchRequest(),
+        return createFRC(
+            fromContext: self.mainContext,
             from: from,
             sectionBy: nil,
             fetchClauses: fetchClauses
@@ -96,128 +92,131 @@ public extension NSFetchedResultsController {
     }
     
     /**
-     Utility for creating an `NSFetchedResultsController` from a `DataStack`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     Utility for creating an `NSFetchedResultsController` from the `DataStack`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `performFetch()` on the created `NSFetchedResultsController`.
      
-     - parameter dataStack: the `DataStack` to observe objects from
      - 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: an `NSFetchedResultsController` that observes a `DataStack`
+     - returns: an `NSFetchedResultsController` that observes the `DataStack`
      */
     @nonobjc
-    public static func createFor(dataStack: DataStack, _ from: From, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController {
+    public func createFetchedResultsController(forDataStack dataStack: DataStack, _ from: From, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController {
         
-        return self.createFromContext(
-            dataStack.mainContext,
-            fetchRequest: CoreStoreFetchRequest(),
+        return createFRC(
+            fromContext: self.mainContext,
             from: from,
             sectionBy: nil,
             fetchClauses: fetchClauses
         )
     }
-    
-    /**
-     Utility for creating an `NSFetchedResultsController` from an `UnsafeDataTransaction`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
-     
-     - parameter transaction: the `UnsafeDataTransaction` to observe objects from
-     - parameter from: a `From` clause indicating the entity type
-     - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections
-     - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
-     - returns: an `NSFetchedResultsController` that observes an `UnsafeDataTransaction`
-     */
-    @nonobjc
-    public static func createFor(transaction: UnsafeDataTransaction, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> NSFetchedResultsController {
-        
-        return self.createFromContext(
-            transaction.context,
-            fetchRequest: CoreStoreFetchRequest(),
-            from: from,
-            sectionBy: sectionBy,
-            fetchClauses: fetchClauses
-        )
-    }
-    
-    /**
-     Utility for creating an `NSFetchedResultsController` from an `UnsafeDataTransaction`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
-     
-     - parameter transaction: the `UnsafeDataTransaction` to observe objects from
-     - parameter from: a `From` clause indicating the entity type
-     - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections
-     - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
-     - returns: an `NSFetchedResultsController` that observes an `UnsafeDataTransaction`
-     */
-    @nonobjc
-    public static func createFor(transaction: UnsafeDataTransaction, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController {
-        
-        return self.createFromContext(
-            transaction.context,
-            fetchRequest: CoreStoreFetchRequest(),
-            from: from,
-            sectionBy: sectionBy,
-            fetchClauses: fetchClauses
-        )
-    }
-    
-    /**
-     Utility for creating an `NSFetchedResultsController` from an `UnsafeDataTransaction`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
-     
-     - parameter transaction: the `UnsafeDataTransaction` to observe objects from
-     - 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: an `NSFetchedResultsController` that observes an `UnsafeDataTransaction`
-     */
-    @nonobjc
-    public static func createFor(transaction: UnsafeDataTransaction, _ from: From, _ fetchClauses: FetchClause...) -> NSFetchedResultsController {
-        
-        return self.createFromContext(
-            transaction.context,
-            fetchRequest: CoreStoreFetchRequest(),
-            from: from,
-            sectionBy: nil,
-            fetchClauses: fetchClauses
-        )
-    }
-    
-    /**
-     Utility for creating an `NSFetchedResultsController` from an `UnsafeDataTransaction`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
-     
-     - parameter transaction: the `UnsafeDataTransaction` to observe objects from
-     - 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.
-     */
-    @nonobjc
-    public static func createFor(transaction: UnsafeDataTransaction, _ from: From, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController {
-        
-        return self.createFromContext(
-            transaction.context,
-            fetchRequest: CoreStoreFetchRequest(),
-            from: from,
-            sectionBy: nil,
-            fetchClauses: fetchClauses
-        )
-    }
-    
-    
-    // MARK: Internal
-    
-    @nonobjc
-    internal static func createFromContext(context: NSManagedObjectContext, fetchRequest: NSFetchRequest, from: From? = nil, sectionBy: SectionBy? = nil, fetchClauses: [FetchClause]) -> NSFetchedResultsController {
-        
-        return CoreStoreFetchedResultsController(
-            context: context,
-            fetchRequest: fetchRequest,
-            from: from,
-            sectionBy: sectionBy,
-            applyFetchClauses: { fetchRequest in
-                
-                fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
-                
-                CoreStore.assert(
-                    fetchRequest.sortDescriptors?.isEmpty == false,
-                    "An \(cs_typeName(NSFetchedResultsController)) requires a sort information. Specify from a \(cs_typeName(OrderBy)) clause or any custom \(cs_typeName(FetchClause)) that provides a sort descriptor."
-                )
-            }
-        )
-    }
 }
 
+
+// MARK: - UnsafeDataTransaction
+
+public extension UnsafeDataTransaction {
+    
+    /**
+     Utility for creating an `NSFetchedResultsController` from the `UnsafeDataTransaction`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `performFetch()` on the created `NSFetchedResultsController`.
+     
+     - parameter from: a `From` clause indicating the entity type
+     - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections
+     - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
+     */
+    @nonobjc
+    public func createFetchedResultsController(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> NSFetchedResultsController {
+        
+        return createFRC(
+            fromContext: self.context,
+            from: from,
+            sectionBy: sectionBy,
+            fetchClauses: fetchClauses
+        )
+    }
+    
+    /**
+     Utility for creating an `NSFetchedResultsController` from the `UnsafeDataTransaction`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `performFetch()` on the created `NSFetchedResultsController`.
+     
+     - parameter from: a `From` clause indicating the entity type
+     - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections
+     - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
+     */
+    @nonobjc
+    public func createFetchedResultsController(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController {
+        
+        return createFRC(
+            fromContext: self.context,
+            from: from,
+            sectionBy: sectionBy,
+            fetchClauses: fetchClauses
+        )
+    }
+    
+    /**
+     Utility for creating an `NSFetchedResultsController` from the `UnsafeDataTransaction`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `performFetch()` on the created `NSFetchedResultsController`.
+     
+     - 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: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
+     */
+    @nonobjc
+    public func createFetchedResultsController(_ from: From, _ fetchClauses: FetchClause...) -> NSFetchedResultsController {
+        
+        return createFRC(
+            fromContext: self.context,
+            from: from,
+            sectionBy: nil,
+            fetchClauses: fetchClauses
+        )
+    }
+    
+    /**
+     Utility for creating an `NSFetchedResultsController` from the `UnsafeDataTransaction`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `ListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `performFetch()` on the created `NSFetchedResultsController`.
+     
+     - 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: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
+     */
+    @nonobjc
+    public func createFetchedResultsController(_ from: From, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController {
+        
+        return createFRC(
+            fromContext: self.context,
+            from: from,
+            sectionBy: nil,
+            fetchClauses: fetchClauses
+        )
+    }
+}
+
+
+
+// MARK: - Private
+
+fileprivate func createFRC(fromContext context: NSManagedObjectContext, from: From? = nil, sectionBy: SectionBy? = nil, fetchClauses: [FetchClause]) -> NSFetchedResultsController {
+    
+    let controller = CoreStoreFetchedResultsController(
+        context: context,
+        fetchRequest: CoreStoreFetchRequest().dynamicCast(),
+        from: from,
+        sectionBy: sectionBy,
+        applyFetchClauses: { (fetchRequest) in
+            
+            fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest) }
+            
+            CoreStore.assert(
+                fetchRequest.sortDescriptors?.isEmpty == false,
+                "An \(cs_typeName(NSFetchedResultsController.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
+            )
+        }
+    )
+    return controller.dynamicCast()
+}
+    
 #endif
diff --git a/Sources/Convenience/NSManagedObject+Convenience.swift b/Sources/Convenience/NSManagedObject+Convenience.swift
index 1e8e134..5900631 100644
--- a/Sources/Convenience/NSManagedObject+Convenience.swift
+++ b/Sources/Convenience/NSManagedObject+Convenience.swift
@@ -31,6 +31,52 @@ import CoreData
 
 public extension NSManagedObject {
     
+    /**
+     Exposes a `FetchableSource` that can fetch sibling objects of this `NSManagedObject` instance. This may be the `DataStack`, a `BaseDataTransaction`, the `NSManagedObjectContext` itself, or `nil` if the obejct's parent is already deallocated.
+     - Warning: Future implementations may change the instance returned by this method depending on the timing or condition that `fetchSource()` was called. Do not make assumptions that the instance will be a specific instance. If the `NSManagedObjectContext` instance is desired, use the `FetchableSource.internalContext()` method to get the correct instance. Also, do not assume that the `fetchSource()` and `querySource()` return the same instance all the time.
+     - returns: a `FetchableSource` that can fetch sibling objects of this `NSManagedObject` instance. This may be the `DataStack`, a `BaseDataTransaction`, the `NSManagedObjectContext` itself, or `nil` if the object's parent is already deallocated.
+     */
+    @nonobjc
+    public func fetchSource() -> FetchableSource? {
+        
+        guard let context = self.managedObjectContext else {
+            
+            return nil
+        }
+        if context.isTransactionContext {
+            
+            return context.parentTransaction
+        }
+        if context.isDataStackContext {
+            
+            return context.parentStack
+        }
+        return context
+    }
+    
+    /**
+     Exposes a `QueryableSource` that can query attributes and aggregate values. This may be the `DataStack`, a `BaseDataTransaction`, the `NSManagedObjectContext` itself, or `nil` if the obejct's parent is already deallocated.
+     - Warning: Future implementations may change the instance returned by this method depending on the timing or condition that `querySource()` was called. Do not make assumptions that the instance will be a specific instance. If the `NSManagedObjectContext` instance is desired, use the `QueryableSource.internalContext()` method to get the correct instance. Also, do not assume that the `fetchSource()` and `querySource()` return the same instance all the time.
+     - returns: a `QueryableSource` that can query attributes and aggregate values. This may be the `DataStack`, a `BaseDataTransaction`, the `NSManagedObjectContext` itself, or `nil` if the object's parent is already deallocated.
+     */
+    @nonobjc
+    public func querySource() -> QueryableSource? {
+        
+        guard let context = self.managedObjectContext else {
+            
+            return nil
+        }
+        if context.isTransactionContext {
+            
+            return context.parentTransaction
+        }
+        if context.isDataStackContext {
+            
+            return context.parentStack
+        }
+        return context
+    }
+    
     /**
      Provides a convenience wrapper for accessing `primitiveValueForKey(...)` with proper calls to `willAccessValueForKey(...)` and `didAccessValueForKey(...)`. This is useful when implementing accessor methods for transient attributes.
      
@@ -38,14 +84,33 @@ public extension NSManagedObject {
      - returns: the primitive value for the KVC key
      */
     @nonobjc
-    @warn_unused_result
-    public func accessValueForKVCKey(KVCKey: KeyPath) -> AnyObject? {
+    public func accessValueForKVCKey(_ KVCKey: KeyPath) -> Any? {
         
-        self.willAccessValueForKey(KVCKey)
-        let primitiveValue: AnyObject? = self.primitiveValueForKey(KVCKey)
-        self.didAccessValueForKey(KVCKey)
+        self.willAccessValue(forKey: KVCKey)
+        defer {
+            
+            self.didAccessValue(forKey: KVCKey)
+        }
+        return self.primitiveValue(forKey: KVCKey)
+    }
+    
+    /**
+     Provides a convenience wrapper for accessing `primitiveValueForKey(...)` with proper calls to `willAccessValueForKey(...)` and `didAccessValueForKey(...)`. This is useful when implementing accessor methods for transient attributes.
+     
+     - parameter KVCKey: the KVC key
+     - parameter didAccessPrimitiveValue: the closure to access the value. This is called between `willAccessValueForKey(...)` and `didAccessValueForKey(...)`
+     - returns: the primitive value for the KVC key
+     */
+    @discardableResult
+    @nonobjc
+    public func accessValueForKVCKey(_ KVCKey: KeyPath, _ didAccessPrimitiveValue: (Any?) throws -> T) rethrows -> T {
         
-        return primitiveValue
+        self.willAccessValue(forKey: KVCKey)
+        defer {
+            
+            self.didAccessValue(forKey: KVCKey)
+        }
+        return try didAccessPrimitiveValue(self.primitiveValue(forKey: KVCKey))
     }
     
     /**
@@ -55,11 +120,34 @@ public extension NSManagedObject {
      - parameter KVCKey: the KVC key
      */
     @nonobjc
-    public func setValue(value: AnyObject?, forKVCKey KVCKey: KeyPath) {
+    public func setValue(_ value: Any?, forKVCKey KVCKey: KeyPath) {
         
-        self.willChangeValueForKey(KVCKey)
+        self.willChangeValue(forKey: KVCKey)
+        defer {
+            
+            self.didChangeValue(forKey: KVCKey)
+        }
         self.setPrimitiveValue(value, forKey: KVCKey)
-        self.didChangeValueForKey(KVCKey)
+    }
+    
+    /**
+     Provides a convenience wrapper for setting `setPrimitiveValue(...)` with proper calls to `willChangeValueForKey(...)` and `didChangeValueForKey(...)`. This is useful when implementing mutator methods for transient attributes.
+     
+     - parameter value: the value to set the KVC key with
+     - parameter KVCKey: the KVC key
+     - parameter didSetPrimitiveValue: the closure called between `willChangeValueForKey(...)` and `didChangeValueForKey(...)`
+     */
+    @discardableResult
+    @nonobjc
+    public func setValue(_ value: Any?, forKVCKey KVCKey: KeyPath, _ didSetPrimitiveValue: (Any?) throws -> T) rethrows -> T {
+        
+        self.willChangeValue(forKey: KVCKey)
+        defer {
+            
+            self.didChangeValue(forKey: KVCKey)
+        }
+        self.setPrimitiveValue(value, forKey: KVCKey)
+        return try didSetPrimitiveValue(value)
     }
     
     /**
@@ -68,7 +156,7 @@ public extension NSManagedObject {
     @nonobjc
     public func refreshAsFault() {
         
-        self.managedObjectContext?.refreshObject(self, mergeChanges: false)
+        self.managedObjectContext?.refresh(self, mergeChanges: false)
     }
     
     /**
@@ -77,6 +165,6 @@ public extension NSManagedObject {
     @nonobjc
     public func refreshAndMerge() {
         
-        self.managedObjectContext?.refreshObject(self, mergeChanges: true)
+        self.managedObjectContext?.refresh(self, mergeChanges: true)
     }
 }
diff --git a/Sources/Convenience/NSProgress+Convenience.swift b/Sources/Convenience/Progress+Convenience.swift
similarity index 70%
rename from Sources/Convenience/NSProgress+Convenience.swift
rename to Sources/Convenience/Progress+Convenience.swift
index 66ec942..bf65903 100644
--- a/Sources/Convenience/NSProgress+Convenience.swift
+++ b/Sources/Convenience/Progress+Convenience.swift
@@ -1,5 +1,5 @@
 //
-//  NSProgress+Convenience.swift
+//  Progress+Convenience.swift
 //  CoreStore
 //
 //  Copyright © 2015 John Rommel Estropia
@@ -24,22 +24,19 @@
 //
 
 import Foundation
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
-// MARK: - NSProgress
+// MARK: - Progress
 
-public extension NSProgress {
+public extension Progress {
     
     /**
-     Sets a closure that the `NSProgress` calls whenever its `fractionCompleted` changes. You can use this instead of setting up KVO.
+     Sets a closure that the `Progress` calls whenever its `fractionCompleted` changes. You can use this instead of setting up KVO.
      
      - parameter closure: the closure to execute on progress change
      */
     @nonobjc
-    public func setProgressHandler(closure: ((progress: NSProgress) -> Void)?) {
+    public func setProgressHandler(_ closure: ((_ progress: Progress) -> Void)?) {
         
         self.progressObserver.progressHandler = closure
     }
@@ -81,8 +78,9 @@ public extension NSProgress {
 @objc
 private final class ProgressObserver: NSObject {
     
-    private unowned let progress: NSProgress
-    private var progressHandler: ((progress: NSProgress) -> Void)? {
+    private unowned let progress: Progress
+    
+    fileprivate var progressHandler: ((_ progress: Progress) -> Void)? {
         
         didSet {
             
@@ -96,19 +94,19 @@ private final class ProgressObserver: NSObject {
                 
                 self.progress.addObserver(
                     self,
-                    forKeyPath: "fractionCompleted",
-                    options: [.Initial, .New],
+                    forKeyPath: #keyPath(Progress.fractionCompleted),
+                    options: [.initial, .new],
                     context: nil
                 )
             }
             else {
                 
-                self.progress.removeObserver(self, forKeyPath: "fractionCompleted")
+                self.progress.removeObserver(self, forKeyPath: #keyPath(Progress.fractionCompleted))
             }
         }
     }
     
-    private init(_ progress: NSProgress) {
+    fileprivate init(_ progress: Progress) {
         
         self.progress = progress
         super.init()
@@ -119,20 +117,22 @@ private final class ProgressObserver: NSObject {
         if let _ = self.progressHandler {
             
             self.progressHandler = nil
-            self.progress.removeObserver(self, forKeyPath: "fractionCompleted")
+            self.progress.removeObserver(self, forKeyPath: #keyPath(Progress.fractionCompleted))
         }
     }
     
-    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer) {
+    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
         
-        guard let progress = object as? NSProgress where progress == self.progress && keyPath == "fractionCompleted" else {
-            
-            return
+        guard let progress = object as? Progress,
+            progress == self.progress,
+            keyPath == #keyPath(Progress.fractionCompleted) else {
+                
+                return
         }
         
-        GCDQueue.Main.async { [weak self] () -> Void in
+        DispatchQueue.main.async { [weak self] () -> Void in
             
-            self?.progressHandler?(progress: progress)
+            self?.progressHandler?(progress)
         }
     }
 }
diff --git a/Sources/CoreStore.swift b/Sources/CoreStore.swift
index e26c83f..718231f 100644
--- a/Sources/CoreStore.swift
+++ b/Sources/CoreStore.swift
@@ -24,9 +24,6 @@
 //
 
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - CoreStore
@@ -45,10 +42,10 @@ public enum CoreStore {
         
         get {
         
-            self.defaultStackBarrierQueue.barrierSync {
-        
+            self.defaultStackBarrierQueue.sync(flags: .barrier) {
+                
                 if self.defaultStackInstance == nil {
-        
+                    
                     self.defaultStackInstance = DataStack()
                 }
             }
@@ -56,7 +53,7 @@ public enum CoreStore {
         }
         set {
             
-            self.defaultStackBarrierQueue.barrierAsync {
+            self.defaultStackBarrierQueue.async(flags: .barrier) {
                 
                 self.defaultStackInstance = newValue
             }
@@ -66,7 +63,7 @@ public enum CoreStore {
     
     // MARK: Private
     
-    private static let defaultStackBarrierQueue = GCDQueue.createConcurrent("com.coreStore.defaultStackBarrierQueue")
+    private static let defaultStackBarrierQueue = DispatchQueue.concurrent("com.coreStore.defaultStackBarrierQueue")
     
     private static var defaultStackInstance: DataStack?
 }
diff --git a/Sources/CoreStoreError.swift b/Sources/CoreStoreError.swift
index 2c854c1..8a87ab8 100644
--- a/Sources/CoreStoreError.swift
+++ b/Sources/CoreStoreError.swift
@@ -32,59 +32,117 @@ import CoreData
 /**
  All errors thrown from CoreStore are expressed in `CoreStoreError` enum values.
  */
-public enum CoreStoreError: ErrorType, Hashable {
+public enum CoreStoreError: Error, CustomNSError, Hashable {
     
     /**
      A failure occured because of an unknown error.
      */
-    case Unknown
+    case unknown
     
     /**
      The `NSPersistentStore` could not be initialized because another store existed at the specified `NSURL`.
      */
-    case DifferentStorageExistsAtURL(existingPersistentStoreURL: NSURL)
+    case differentStorageExistsAtURL(existingPersistentStoreURL: URL)
     
     /**
      An `NSMappingModel` could not be found for a specific source and destination model versions.
      */
-    case MappingModelNotFound(localStoreURL: NSURL, targetModel: NSManagedObjectModel, targetModelVersion: String)
+    case mappingModelNotFound(localStoreURL: URL, targetModel: NSManagedObjectModel, targetModelVersion: String)
     
     /**
      Progressive migrations are disabled for a store, but an `NSMappingModel` could not be found for a specific source and destination model versions.
      */
-    case ProgressiveMigrationRequired(localStoreURL: NSURL)
+    case progressiveMigrationRequired(localStoreURL: URL)
     
     /**
      An internal SDK call failed with the specified `NSError`.
      */
-    case InternalError(NSError: NSError)
+    case internalError(NSError: NSError)
     
     
-    // MARK: ErrorType
+    // MARK: CustomNSError
     
-    public var _domain: String {
+    public static var errorDomain: String {
         
         return CoreStoreErrorDomain
     }
     
-    public var _code: Int {
+    public var errorCode: Int {
     
         switch self {
             
-        case .Unknown:
-            return CoreStoreErrorCode.UnknownError.rawValue
+        case .unknown:
+            return CoreStoreErrorCode.unknownError.rawValue
             
-        case .DifferentStorageExistsAtURL:
-            return CoreStoreErrorCode.DifferentPersistentStoreExistsAtURL.rawValue
+        case .differentStorageExistsAtURL:
+            return CoreStoreErrorCode.differentStorageExistsAtURL.rawValue
             
-        case .MappingModelNotFound:
-            return CoreStoreErrorCode.MappingModelNotFound.rawValue
+        case .mappingModelNotFound:
+            return CoreStoreErrorCode.mappingModelNotFound.rawValue
             
-        case .ProgressiveMigrationRequired:
-            return CoreStoreErrorCode.ProgressiveMigrationRequired.rawValue
+        case .progressiveMigrationRequired:
+            return CoreStoreErrorCode.progressiveMigrationRequired.rawValue
             
-        case .InternalError:
-            return CoreStoreErrorCode.InternalError.rawValue
+        case .internalError:
+            return CoreStoreErrorCode.internalError.rawValue
+        }
+    }
+    
+    public var errorUserInfo: [String : Any] {
+        
+        switch self {
+            
+        case .unknown:
+            return [:]
+            
+        case .differentStorageExistsAtURL(let existingPersistentStoreURL):
+            return [
+                "existingPersistentStoreURL": existingPersistentStoreURL
+            ]
+            
+        case .mappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
+            return [
+                "localStoreURL": localStoreURL,
+                "targetModel": targetModel,
+                "targetModelVersion": targetModelVersion
+            ]
+            
+        case .progressiveMigrationRequired(let localStoreURL):
+            return [
+                "localStoreURL": localStoreURL
+            ]
+            
+        case .internalError(let NSError):
+            return [
+                "NSError": NSError
+            ]
+        }
+    }
+    
+    
+    // MARK: Equatable
+    
+    public static func == (lhs: CoreStoreError, rhs: CoreStoreError) -> Bool {
+        
+        switch (lhs, rhs) {
+            
+        case (.unknown, .unknown):
+            return true
+            
+        case (.differentStorageExistsAtURL(let url1), .differentStorageExistsAtURL(let url2)):
+            return url1 == url2
+            
+        case (.mappingModelNotFound(let url1, let model1, let version1), .mappingModelNotFound(let url2, let model2, let version2)):
+            return url1 == url2 && model1 == model2 && version1 == version2
+            
+        case (.progressiveMigrationRequired(let url1), .progressiveMigrationRequired(let url2)):
+            return url1 == url2
+            
+        case (.internalError(let NSError1), .internalError(let NSError2)):
+            return NSError1 == NSError2
+            
+        default:
+            return false
         }
     }
     
@@ -96,19 +154,19 @@ public enum CoreStoreError: ErrorType, Hashable {
         let code = self._code
         switch self {
             
-        case .Unknown:
+        case .unknown:
             return code.hashValue
             
-        case .DifferentStorageExistsAtURL(let existingPersistentStoreURL):
+        case .differentStorageExistsAtURL(let existingPersistentStoreURL):
             return code.hashValue ^ existingPersistentStoreURL.hashValue
             
-        case .MappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
+        case .mappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
             return code.hashValue ^ localStoreURL.hashValue ^ targetModel.hashValue ^ targetModelVersion.hashValue
             
-        case .ProgressiveMigrationRequired(let localStoreURL):
+        case .progressiveMigrationRequired(let localStoreURL):
             return code.hashValue ^ localStoreURL.hashValue
             
-        case .InternalError(let NSError):
+        case .internalError(let NSError):
             return code.hashValue ^ NSError.hashValue
         }
     }
@@ -116,37 +174,9 @@ public enum CoreStoreError: ErrorType, Hashable {
     
     // MARK: Internal
     
-    internal init(_ error: ErrorType?) {
+    internal init(_ error: Error?) {
         
-        self = error.flatMap { $0.bridgeToSwift } ?? .Unknown
-    }
-}
-
-
-// MARK: - CoreStoreError: Equatable
-
-@warn_unused_result
-public func == (lhs: CoreStoreError, rhs: CoreStoreError) -> Bool {
-    
-    switch (lhs, rhs) {
-        
-    case (.Unknown, .Unknown):
-        return true
-        
-    case (.DifferentStorageExistsAtURL(let url1), .DifferentStorageExistsAtURL(let url2)):
-        return url1 == url2
-        
-    case (.MappingModelNotFound(let url1, let model1, let version1), .MappingModelNotFound(let url2, let model2, let version2)):
-        return url1 == url2 && model1 == model2 && version1 == version2
-        
-    case (.ProgressiveMigrationRequired(let url1), .ProgressiveMigrationRequired(let url2)):
-        return url1 == url2
-        
-    case (.InternalError(let NSError1), .InternalError(let NSError2)):
-        return NSError1 == NSError2
-        
-    default:
-        return false
+        self = error.flatMap { $0.bridgeToSwift } ?? .unknown
     }
 }
 
@@ -170,27 +200,27 @@ public enum CoreStoreErrorCode: Int {
     /**
      A failure occured because of an unknown error.
      */
-    case UnknownError
+    case unknownError
     
     /**
      The `NSPersistentStore` could note be initialized because another store existed at the specified `NSURL`.
      */
-    case DifferentPersistentStoreExistsAtURL
+    case differentStorageExistsAtURL
     
     /**
      An `NSMappingModel` could not be found for a specific source and destination model versions.
      */
-    case MappingModelNotFound
+    case mappingModelNotFound
     
     /**
      Progressive migrations are disabled for a store, but an `NSMappingModel` could not be found for a specific source and destination model versions.
      */
-    case ProgressiveMigrationRequired
+    case progressiveMigrationRequired
     
     /**
      An internal SDK call failed with the specified "NSError" userInfo key.
      */
-    case InternalError
+    case internalError
 }
 
 
@@ -208,20 +238,4 @@ public extension NSError {
             || code == NSMigrationError)
             && self.domain == NSCocoaErrorDomain
     }
-    
-    
-    // MARK: Deprecated
-
-    /**
-     Deprecated. Use `CoreStoreError` enum values instead.
-     
-     If the error's domain is equal to `CoreStoreErrorDomain`, returns the associated `CoreStoreErrorCode`. For other domains, returns `nil`.
-     */
-    @available(*, deprecated=2.0.0, message="Use CoreStoreError enum values instead.")
-    public var coreStoreErrorCode: CoreStoreErrorCode? {
-        
-        return (self.domain == CoreStoreErrorDomain
-            ? CoreStoreErrorCode(rawValue: self.code)
-            : nil)
-    }
 }
diff --git a/Sources/Fetching and Querying/BaseDataTransaction+Querying.swift b/Sources/Fetching and Querying/BaseDataTransaction+Querying.swift
index 6106d6b..777bcd0 100644
--- a/Sources/Fetching and Querying/BaseDataTransaction+Querying.swift	
+++ b/Sources/Fetching and Querying/BaseDataTransaction+Querying.swift	
@@ -29,7 +29,46 @@ import CoreData
 
 // MARK: - DataTransaction
 
-public extension BaseDataTransaction {
+extension BaseDataTransaction: FetchableSource, QueryableSource {
+    
+    /**
+     Deletes all `NSManagedObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     
+     - parameter from: a `From` clause indicating the entity type
+     - parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the number of `NSManagedObject`s deleted
+     */
+    @discardableResult
+    public func deleteAll(_ from: From, _ deleteClauses: DeleteClause...) -> Int? {
+        
+        CoreStore.assert(
+            self.isRunningInAllowedQueue(),
+            "Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
+        )
+        
+        return self.context.deleteAll(from, deleteClauses)
+    }
+    
+    /**
+     Deletes all `NSManagedObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     
+     - parameter from: a `From` clause indicating the entity type
+     - parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the number of `NSManagedObject`s deleted
+     */
+    @discardableResult
+    public func deleteAll(_ from: From, _ deleteClauses: [DeleteClause]) -> Int? {
+        
+        CoreStore.assert(
+            self.isRunningInAllowedQueue(),
+            "Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
+        )
+        
+        return self.context.deleteAll(from, deleteClauses)
+    }
+    
+    
+    // MARK: FetchableSource
     
     /**
      Fetches the `NSManagedObject` instance in the transaction's context from a reference created from a transaction or from a different managed object context.
@@ -37,17 +76,9 @@ 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(object: T) -> T? {
+    public func fetchExisting(_ object: T) -> T? {
         
-        do {
-            
-            return (try self.context.existingObjectWithID(object.objectID) as! T)
-        }
-        catch _ {
-            
-            return nil
-        }
+        return self.context.fetchExisting(object)
     }
     
     /**
@@ -56,17 +87,9 @@ 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(objectID: NSManagedObjectID) -> T? {
+    public func fetchExisting(_ objectID: NSManagedObjectID) -> T? {
         
-        do {
-            
-            return (try self.context.existingObjectWithID(objectID) as! T)
-        }
-        catch _ {
-            
-            return nil
-        }
+        return self.context.fetchExisting(objectID)
     }
     
     /**
@@ -75,10 +98,9 @@ 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
      */
-    @warn_unused_result
-    public func fetchExisting(objects: S) -> [T] {
+    public func fetchExisting(_ objects: S) -> [T] where S.Iterator.Element == T {
         
-        return objects.flatMap { (try? self.context.existingObjectWithID($0.objectID)) as? T }
+        return self.context.fetchExisting(objects)
     }
     
     /**
@@ -87,10 +109,9 @@ public extension BaseDataTransaction {
      - parameter objectIDs: the `NSManagedObjectID` array for the objects
      - returns: the `NSManagedObject` array for objects that exists in the transaction
      */
-    @warn_unused_result
-    public func fetchExisting(objectIDs: S) -> [T] {
+    public func fetchExisting(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
         
-        return objectIDs.flatMap { (try? self.context.existingObjectWithID($0)) as? T }
+        return self.context.fetchExisting(objectIDs)
     }
     
     /**
@@ -100,10 +121,13 @@ 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(from: From, _ fetchClauses: FetchClause...) -> T? {
+    public func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? {
         
-        return self.fetchOne(from, fetchClauses)
+        CoreStore.assert(
+            self.isRunningInAllowedQueue(),
+            "Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
+        )
+        return self.context.fetchOne(from, fetchClauses)
     }
     
     /**
@@ -113,8 +137,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(from: From, _ fetchClauses: [FetchClause]) -> T? {
+    public func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
@@ -130,10 +153,13 @@ 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(from: From, _ fetchClauses: FetchClause...) -> [T]? {
+    public func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? {
         
-        return self.fetchAll(from, fetchClauses)
+        CoreStore.assert(
+            self.isRunningInAllowedQueue(),
+            "Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
+        )
+        return self.context.fetchAll(from, fetchClauses)
     }
     
     /**
@@ -143,8 +169,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(from: From, _ fetchClauses: [FetchClause]) -> [T]? {
+    public func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
@@ -160,10 +185,13 @@ 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(from: From, _ fetchClauses: FetchClause...) -> Int? {
+    public func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? {
         
-        return self.fetchCount(from, fetchClauses)
+        CoreStore.assert(
+            self.isRunningInAllowedQueue(),
+            "Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
+        )
+        return self.context.fetchCount(from, fetchClauses)
     }
     
     /**
@@ -173,14 +201,12 @@ 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(from: From, _ fetchClauses: [FetchClause]) -> Int? {
+    public func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
             "Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
         )
-        
         return self.context.fetchCount(from, fetchClauses)
     }
     
@@ -191,10 +217,13 @@ 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(from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
+    public func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
         
-        return self.fetchObjectID(from, fetchClauses)
+        CoreStore.assert(
+            self.isRunningInAllowedQueue(),
+            "Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
+        )
+        return self.context.fetchObjectID(from, fetchClauses)
     }
     
     /**
@@ -204,8 +233,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(from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
+    public func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
@@ -221,21 +249,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(from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
-        
-        return self.fetchObjectIDs(from, fetchClauses)
-    }
-    
-    /**
-     Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
-     
-     - parameter from: a `From` clause indicating the entity type
-     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
-     - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
-     */
-    @warn_unused_result
-    public func fetchObjectIDs(from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
+    public func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
@@ -245,38 +259,23 @@ public extension BaseDataTransaction {
     }
     
     /**
-     Deletes all `NSManagedObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      
      - parameter from: a `From` clause indicating the entity type
-     - parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
-     - returns: the number of `NSManagedObject`s deleted
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
      */
-    public func deleteAll(from: From, _ deleteClauses: DeleteClause...) -> Int? {
+    public func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
-            "Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
+            "Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
         )
-        
-        return self.context.deleteAll(from, deleteClauses)
+        return self.context.fetchObjectIDs(from, fetchClauses)
     }
     
-    /**
-     Deletes all `NSManagedObject`s that satisfy the specified `DeleteClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
-     
-     - parameter from: a `From` clause indicating the entity type
-     - parameter deleteClauses: a series of `DeleteClause` instances for the delete request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
-     - returns: the number of `NSManagedObject`s deleted
-     */
-    public func deleteAll(from: From, _ deleteClauses: [DeleteClause]) -> Int? {
-        
-        CoreStore.assert(
-            self.isRunningInAllowedQueue(),
-            "Attempted to delete from a \(cs_typeName(self)) outside its designated queue."
-        )
-        
-        return self.context.deleteAll(from, deleteClauses)
-    }
+    
+    // MARK: QueryableSource
     
     /**
      Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
@@ -288,14 +287,12 @@ public extension BaseDataTransaction {
      - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter.
      */
-    @warn_unused_result
-    public func queryValue(from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? {
+    public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
             "Attempted to query from a \(cs_typeName(self)) outside its designated queue."
         )
-        
         return self.context.queryValue(from, selectClause, queryClauses)
     }
     
@@ -309,14 +306,12 @@ public extension BaseDataTransaction {
      - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter.
      */
-    @warn_unused_result
-    public func queryValue(from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? {
+    public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
             "Attempted to query from a \(cs_typeName(self)) outside its designated queue."
         )
-        
         return self.context.queryValue(from, selectClause, queryClauses)
     }
     
@@ -330,14 +325,12 @@ public extension BaseDataTransaction {
      - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter.
      */
-    @warn_unused_result
-    public func queryAttributes(from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
+    public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
             "Attempted to query from a \(cs_typeName(self)) outside its designated queue."
         )
-        
         return self.context.queryAttributes(from, selectClause, queryClauses)
     }
     
@@ -351,14 +344,23 @@ 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` parameter.
      */
-    @warn_unused_result
-    public func queryAttributes(from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
+    public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
             "Attempted to query from a \(cs_typeName(self)) outside its designated queue."
         )
-        
         return self.context.queryAttributes(from, selectClause, queryClauses)
     }
+    
+    
+    // MARK: FetchableSource, QueryableSource
+    
+    /**
+     The internal `NSManagedObjectContext` managed by this instance. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases.
+     */
+    public func internalContext() -> NSManagedObjectContext {
+        
+        return self.context
+    }
 }
diff --git a/Sources/Fetching and Querying/Concrete Clauses/From.swift b/Sources/Fetching and Querying/Concrete Clauses/From.swift
index e5f43db..c0bb44e 100644
--- a/Sources/Fetching and Querying/Concrete Clauses/From.swift	
+++ b/Sources/Fetching and Querying/Concrete Clauses/From.swift	
@@ -32,7 +32,7 @@ import CoreData
 /**
  A `From` clause specifies the source entity and source persistent store for fetch and query methods. A common usage is to just indicate the entity:
  ```
- let person = transaction.fetchOne(From(MyPersonEntity))
+ let person = transaction.fetchOne(From())
  ```
  For cases where multiple `NSPersistentStore`s contain the same entity, the source configuration's name needs to be specified as well:
  ```
@@ -58,7 +58,7 @@ public struct From {
      let people = transaction.fetchAll(From())
      ```
      */
-    public init(){
+    public init() {
         
         self.init(entityClass: T.self, configurations: nil)
     }
@@ -68,7 +68,6 @@ public struct From {
      ```
      let people = transaction.fetchAll(From())
      ```
-     
      - parameter entity: the associated `NSManagedObject` type
      */
     public init(_ entity: T.Type) {
@@ -81,14 +80,13 @@ public struct From {
      ```
      let people = transaction.fetchAll(From())
      ```
-     
      - parameter entityClass: the associated `NSManagedObject` entity class
      */
     public init(_ entityClass: AnyClass) {
         
         CoreStore.assert(
             entityClass is T.Type,
-            "Attempted to create generic type \(cs_typeName(From)) with entity class \(cs_typeName(entityClass))"
+            "Attempted to create generic type \(cs_typeName(From.self)) with entity class \(cs_typeName(entityClass))"
         )
         self.init(entityClass: entityClass, configurations: nil)
     }
@@ -98,7 +96,6 @@ public struct From {
      ```
      let people = transaction.fetchAll(From(nil, "Configuration1"))
      ```
-     
      - parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      - parameter otherConfigurations: an optional list of other configuration names to associate objects from (see `configuration` parameter)
      */
@@ -112,7 +109,6 @@ public struct From {
      ```
      let people = transaction.fetchAll(From(["Configuration1", "Configuration2"]))
      ```
-     
      - parameter configurations: a list of `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      */
     public init(_ configurations: [String?]) {
@@ -125,7 +121,6 @@ public struct From {
      ```
      let people = transaction.fetchAll(From(MyPersonEntity.self, nil, "Configuration1"))
      ```
-     
      - parameter entity: the associated `NSManagedObject` type
      - parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      - parameter otherConfigurations: an optional list of other configuration names to associate objects from (see `configuration` parameter)
@@ -140,7 +135,6 @@ public struct From {
      ```
      let people = transaction.fetchAll(From(MyPersonEntity.self, ["Configuration1", "Configuration1"]))
      ```
-     
      - parameter entity: the associated `NSManagedObject` type
      - parameter configurations: a list of `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      */
@@ -154,7 +148,6 @@ public struct From {
      ```
      let people = transaction.fetchAll(From(MyPersonEntity.self, nil, "Configuration1"))
      ```
-     
      - parameter entity: the associated `NSManagedObject` entity class
      - parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      - parameter otherConfigurations: an optional list of other configuration names to associate objects from (see `configuration` parameter)
@@ -163,7 +156,7 @@ public struct From {
         
         CoreStore.assert(
             entityClass is T.Type,
-            "Attempted to create generic type \(cs_typeName(From)) with entity class \(cs_typeName(entityClass))"
+            "Attempted to create generic type \(cs_typeName(From.self)) with entity class \(cs_typeName(entityClass))"
         )
         self.init(entityClass: entityClass, configurations: [configuration] + otherConfigurations)
     }
@@ -173,7 +166,6 @@ public struct From {
      ```
      let people = transaction.fetchAll(From(MyPersonEntity.self, ["Configuration1", "Configuration1"]))
      ```
-     
      - parameter entity: the associated `NSManagedObject` entity class
      - parameter configurations: a list of `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      */
@@ -181,7 +173,7 @@ public struct From {
         
         CoreStore.assert(
             entityClass is T.Type,
-            "Attempted to create generic type \(cs_typeName(From)) with entity class \(cs_typeName(entityClass))"
+            "Attempted to create generic type \(cs_typeName(From.self)) with entity class \(cs_typeName(entityClass))"
         )
         self.init(entityClass: entityClass, configurations: configurations)
     }
@@ -189,8 +181,7 @@ public struct From {
     
     // MARK: Internal
     
-    @warn_unused_result
-    internal func applyToFetchRequest(fetchRequest: NSFetchRequest, context: NSManagedObjectContext, applyAffectedStores: Bool = true) -> Bool {
+    internal func applyToFetchRequest(_ fetchRequest: NSFetchRequest, context: NSManagedObjectContext, applyAffectedStores: Bool = true) -> Bool {
         
         fetchRequest.entity = context.entityDescriptionForEntityClass(self.entityClass)
         guard applyAffectedStores else {
@@ -202,15 +193,15 @@ public struct From {
             return true
         }
         CoreStore.log(
-            .Warning,
+            .warning,
             message: "Attempted to perform a fetch but could not find any persistent store for the entity \(cs_typeName(fetchRequest.entityName))"
         )
         return false
     }
     
-    internal func applyAffectedStoresForFetchedRequest(fetchRequest: NSFetchRequest, context: NSManagedObjectContext) -> Bool {
+    internal func applyAffectedStoresForFetchedRequest(_ fetchRequest: NSFetchRequest, context: NSManagedObjectContext) -> Bool {
         
-        let stores = self.findPersistentStores(context: context)
+        let stores = self.findPersistentStores(context)
         fetchRequest.affectedStores = stores
         return stores?.isEmpty == false
     }
@@ -227,7 +218,7 @@ public struct From {
     
     // MARK: Private
     
-    private let findPersistentStores: (context: NSManagedObjectContext) -> [NSPersistentStore]?
+    private let findPersistentStores: (_ context: NSManagedObjectContext) -> [NSPersistentStore]?
     
     private init(entityClass: AnyClass, configurations: [String?]?) {
         
@@ -253,121 +244,10 @@ public struct From {
         }
     }
     
-    private init(entityClass: AnyClass, configurations: [String?]?, findPersistentStores: (context: NSManagedObjectContext) -> [NSPersistentStore]?) {
+    private init(entityClass: AnyClass, configurations: [String?]?, findPersistentStores: @escaping (_ context: NSManagedObjectContext) -> [NSPersistentStore]?) {
         
         self.entityClass = entityClass
         self.configurations = configurations
         self.findPersistentStores = findPersistentStores
     }
-    
-    
-    // MARK: Obsolete
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ storeURL: NSURL, _ otherStoreURLs: NSURL...) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ storeURLs: [NSURL]) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ entity: T.Type, _ storeURL: NSURL, _ otherStoreURLs: NSURL...) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ entity: T.Type, _ storeURLs: [NSURL]) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ entityClass: AnyClass, _ storeURL: NSURL, _ otherStoreURLs: NSURL...) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ entityClass: AnyClass, _ storeURLs: [NSURL]) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ persistentStore: NSPersistentStore, _ otherPersistentStores: NSPersistentStore...) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ persistentStores: [NSPersistentStore]) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ entity: T.Type, _ persistentStore: NSPersistentStore, _ otherPersistentStores: NSPersistentStore...) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ entity: T.Type, _ persistentStores: [NSPersistentStore]) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ entityClass: AnyClass, _ persistentStore: NSPersistentStore, _ otherPersistentStores: NSPersistentStore...) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
-    
-    /**
-     Obsolete. Use initializers that accept configuration names.
-     */
-    @available(*, obsoleted=2.0.0, message="Use initializers that accept configuration names.")
-    public init(_ entityClass: AnyClass, _ persistentStores: [NSPersistentStore]) {
-        
-        CoreStore.abort("Use initializers that accept configuration names.")
-    }
 }
diff --git a/Sources/Fetching and Querying/Concrete Clauses/GroupBy.swift b/Sources/Fetching and Querying/Concrete Clauses/GroupBy.swift
index a18a39b..842b713 100644
--- a/Sources/Fetching and Querying/Concrete Clauses/GroupBy.swift	
+++ b/Sources/Fetching and Querying/Concrete Clauses/GroupBy.swift	
@@ -71,13 +71,13 @@ public struct GroupBy: QueryClause, Hashable {
     
     // MARK: QueryClause
     
-    public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
+    public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) {
         
-        if let keyPaths = fetchRequest.propertiesToGroupBy as? [String] where keyPaths != self.keyPaths {
+        if let keyPaths = fetchRequest.propertiesToGroupBy as? [String], keyPaths != self.keyPaths {
             
             CoreStore.log(
-                .Warning,
-                message: "An existing \"propertiesToGroupBy\" for the \(cs_typeName(NSFetchRequest)) was overwritten by \(cs_typeName(self)) query clause."
+                .warning,
+                message: "An existing \"propertiesToGroupBy\" for the \(cs_typeName(NSFetchRequest.self)) was overwritten by \(cs_typeName(self)) query clause."
             )
         }
         
@@ -85,6 +85,14 @@ public struct GroupBy: QueryClause, Hashable {
     }
     
     
+    // MARK: Equatable
+    
+    public static func == (lhs: GroupBy, rhs: GroupBy) -> Bool {
+        
+        return lhs.keyPaths == rhs.keyPaths
+    }
+    
+    
     // MARK: Hashable
     
     public var hashValue: Int {
@@ -92,12 +100,3 @@ public struct GroupBy: QueryClause, Hashable {
         return (self.keyPaths as NSArray).hashValue
     }
 }
-
-
-// MARK: - GroupBy: Equatable
-
-@warn_unused_result
-public func == (lhs: GroupBy, rhs: GroupBy) -> Bool {
-    
-    return lhs.keyPaths == rhs.keyPaths
-}
diff --git a/Sources/Fetching and Querying/Concrete Clauses/OrderBy.swift b/Sources/Fetching and Querying/Concrete Clauses/OrderBy.swift
index f90ee96..76bb49d 100644
--- a/Sources/Fetching and Querying/Concrete Clauses/OrderBy.swift	
+++ b/Sources/Fetching and Querying/Concrete Clauses/OrderBy.swift	
@@ -27,12 +27,12 @@ import Foundation
 import CoreData
 
 
-public func +(left: OrderBy, right: OrderBy) -> OrderBy {
+public func + (left: OrderBy, right: OrderBy) -> OrderBy {
     
     return OrderBy(left.sortDescriptors + right.sortDescriptors)
 }
 
-public func +=(inout left: OrderBy, right: OrderBy) {
+public func += (left: inout OrderBy, right: OrderBy) {
     
     left = left + right
 }
@@ -53,12 +53,12 @@ public enum SortKey {
     /**
      Indicates that the `KeyPath` should be sorted in ascending order
      */
-    case Ascending(KeyPath)
+    case ascending(KeyPath)
     
     /**
      Indicates that the `KeyPath` should be sorted in descending order
      */
-    case Descending(KeyPath)
+    case descending(KeyPath)
 }
 
 
@@ -114,10 +114,10 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause, Hashable {
                 
                 switch sortKey {
                     
-                case .Ascending(let keyPath):
+                case .ascending(let keyPath):
                     return NSSortDescriptor(key: keyPath, ascending: true)
                     
-                case .Descending(let keyPath):
+                case .descending(let keyPath):
                     return NSSortDescriptor(key: keyPath, ascending: false)
                 }
             }
@@ -138,13 +138,13 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause, Hashable {
     
     // MARK: FetchClause, QueryClause, DeleteClause
     
-    public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
+    public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) {
         
-        if let sortDescriptors = fetchRequest.sortDescriptors where sortDescriptors != self.sortDescriptors {
+        if let sortDescriptors = fetchRequest.sortDescriptors, sortDescriptors != self.sortDescriptors {
             
             CoreStore.log(
-                .Warning,
-                message: "Existing sortDescriptors for the \(cs_typeName(NSFetchRequest)) was overwritten by \(cs_typeName(self)) query clause."
+                .warning,
+                message: "Existing sortDescriptors for the \(cs_typeName(fetchRequest)) was overwritten by \(cs_typeName(self)) query clause."
             )
         }
         
@@ -152,6 +152,14 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause, Hashable {
     }
     
     
+    // MARK: Equatable
+    
+    public static func == (lhs: OrderBy, rhs: OrderBy) -> Bool {
+        
+        return lhs.sortDescriptors == rhs.sortDescriptors
+    }
+    
+    
     // MARK: Hashable
     
     public var hashValue: Int {
@@ -159,12 +167,3 @@ public struct OrderBy: FetchClause, QueryClause, DeleteClause, Hashable {
         return (self.sortDescriptors as NSArray).hashValue
     }
 }
-
-
-// MARK: - OrderBy: Equatable
-
-@warn_unused_result
-public func == (lhs: OrderBy, rhs: OrderBy) -> Bool {
-    
-    return lhs.sortDescriptors == rhs.sortDescriptors
-}
diff --git a/Sources/Fetching and Querying/Concrete Clauses/Select.swift b/Sources/Fetching and Querying/Concrete Clauses/Select.swift
index 040e8ce..89f7a9b 100644
--- a/Sources/Fetching and Querying/Concrete Clauses/Select.swift	
+++ b/Sources/Fetching and Querying/Concrete Clauses/Select.swift	
@@ -44,7 +44,7 @@ public protocol SelectValueResultType: SelectResultType {
     
     static var attributeType: NSAttributeType { get }
     
-    static func fromResultObject(result: AnyObject) -> Self?
+    static func fromResultObject(_ result: Any) -> Self?
 }
 
 
@@ -55,7 +55,7 @@ public protocol SelectValueResultType: SelectResultType {
  */
 public protocol SelectAttributesResultType: SelectResultType {
     
-    static func fromResultObjects(result: [AnyObject]) -> [[NSString: AnyObject]]
+    static func fromResultObjects(_ result: [Any]) -> [[String: Any]]
 }
 
 
@@ -64,54 +64,52 @@ public protocol SelectAttributesResultType: SelectResultType {
 /**
  The `SelectTerm` is passed to the `Select` clause to indicate the attributes/aggregate keys to be queried.
  */
-public enum SelectTerm: StringLiteralConvertible, Hashable {
+public enum SelectTerm: ExpressibleByStringLiteral, Hashable {
     
     /**
      Provides a `SelectTerm` to a `Select` clause for querying an entity attribute. A shorter way to do the same is to assign from the string keypath directly:
      ```
      let fullName = CoreStore.queryValue(
-         From(MyPersonEntity),
-         Select(.Attribute("fullName")),
+         From(),
+         Select(.attribute("fullName")),
          Where("employeeID", isEqualTo: 1111)
      )
      ```
      is equivalent to:
      ```
      let fullName = CoreStore.queryValue(
-         From(MyPersonEntity),
+         From(),
          Select("fullName"),
          Where("employeeID", isEqualTo: 1111)
      )
      ```
-     
      - parameter keyPath: the attribute name
      - returns: a `SelectTerm` to a `Select` clause for querying an entity attribute
      */
-    public static func Attribute(keyPath: KeyPath) -> SelectTerm {
+    public static func attribute(_ keyPath: KeyPath) -> SelectTerm {
         
-        return ._Attribute(keyPath)
+        return ._attribute(keyPath)
     }
     
     /**
      Provides a `SelectTerm` to a `Select` clause for querying the average value of an attribute.
      ```
      let averageAge = CoreStore.queryValue(
-         From(MyPersonEntity),
-         Select(.Average("age"))
+         From(),
+         Select(.average("age"))
      )
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "average()" is used
      - returns: a `SelectTerm` to a `Select` clause for querying the average value of an attribute
      */
-    public static func Average(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
+    public static func average(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
         
-        return ._Aggregate(
+        return ._aggregate(
             function: "average:",
             keyPath: keyPath,
             alias: alias ?? "average(\(keyPath))",
-            nativeType: .DecimalAttributeType
+            nativeType: .decimalAttributeType
         )
     }
     
@@ -119,22 +117,21 @@ public enum SelectTerm: StringLiteralConvertible, Hashable {
      Provides a `SelectTerm` to a `Select` clause for a count query.
      ```
      let numberOfEmployees = CoreStore.queryValue(
-         From(MyPersonEntity),
-         Select(.Count("employeeID"))
+         From(),
+         Select(.count("employeeID"))
      )
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "count()" is used
      - returns: a `SelectTerm` to a `Select` clause for a count query
      */
-    public static func Count(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
+    public static func count(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
         
-        return ._Aggregate(
+        return ._aggregate(
             function: "count:",
             keyPath: keyPath,
             alias: alias ?? "count(\(keyPath))",
-            nativeType: .Integer64AttributeType
+            nativeType: .integer64AttributeType
         )
     }
     
@@ -142,22 +139,21 @@ public enum SelectTerm: StringLiteralConvertible, Hashable {
      Provides a `SelectTerm` to a `Select` clause for querying the maximum value for an attribute.
      ```
      let maximumAge = CoreStore.queryValue(
-         From(MyPersonEntity),
-         Select(.Maximum("age"))
+         From(),
+         Select(.maximum("age"))
      )
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "max()" is used
      - returns: a `SelectTerm` to a `Select` clause for querying the maximum value for an attribute
      */
-    public static func Maximum(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
+    public static func maximum(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
         
-        return ._Aggregate(
+        return ._aggregate(
             function: "max:",
             keyPath: keyPath,
             alias: alias ?? "max(\(keyPath))",
-            nativeType: .UndefinedAttributeType
+            nativeType: .undefinedAttributeType
         )
     }
     
@@ -165,22 +161,21 @@ public enum SelectTerm: StringLiteralConvertible, Hashable {
      Provides a `SelectTerm` to a `Select` clause for querying the minimum value for an attribute.
      ```
      let minimumAge = CoreStore.queryValue(
-         From(MyPersonEntity),
-         Select(.Minimum("age"))
+         From(),
+         Select(.minimum("age"))
      )
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "min()" is used
      - returns: a `SelectTerm` to a `Select` clause for querying the minimum value for an attribute
      */
-    public static func Minimum(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
+    public static func minimum(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
         
-        return ._Aggregate(
+        return ._aggregate(
             function: "min:",
             keyPath: keyPath,
             alias: alias ?? "min(\(keyPath))",
-            nativeType: .UndefinedAttributeType
+            nativeType: .undefinedAttributeType
         )
     }
     
@@ -188,22 +183,21 @@ public enum SelectTerm: StringLiteralConvertible, Hashable {
      Provides a `SelectTerm` to a `Select` clause for querying the sum value for an attribute.
      ```
      let totalAge = CoreStore.queryValue(
-         From(MyPersonEntity),
-         Select(.Sum("age"))
+         From(),
+         Select(.sum("age"))
      )
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "sum()" is used
      - returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
      */
-    public static func Sum(keyPath: KeyPath, As alias: KeyPath? = nil) -> SelectTerm {
+    public static func sum(_ keyPath: KeyPath, as alias: KeyPath? = nil) -> SelectTerm {
         
-        return ._Aggregate(
+        return ._aggregate(
             function: "sum:",
             keyPath: keyPath,
             alias: alias ?? "sum(\(keyPath))",
-            nativeType: .DecimalAttributeType
+            nativeType: .decimalAttributeType
         )
     }
     
@@ -211,40 +205,64 @@ public enum SelectTerm: StringLiteralConvertible, Hashable {
      Provides a `SelectTerm` to a `Select` clause for querying the `NSManagedObjectID`.
      ```
      let objectID = CoreStore.queryValue(
-         From(MyPersonEntity),
+         From(),
          Select(),
          Where("employeeID", isEqualTo: 1111)
      )
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "objecID" is used
      - returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
      */
-    public static func ObjectID(As alias: KeyPath? = nil) -> SelectTerm {
+    public static func objectID(as alias: KeyPath? = nil) -> SelectTerm {
         
-        return ._Identity(
+        return ._identity(
             alias: alias ?? "objectID",
-            nativeType: .ObjectIDAttributeType
+            nativeType: .objectIDAttributeType
         )
     }
     
     
-    // MARK: StringLiteralConvertible
+    // MARK: ExpressibleByStringLiteral
     
     public init(stringLiteral value: KeyPath) {
         
-        self = ._Attribute(value)
+        self = ._attribute(value)
     }
     
     public init(unicodeScalarLiteral value: KeyPath) {
         
-        self = ._Attribute(value)
+        self = ._attribute(value)
     }
     
     public init(extendedGraphemeClusterLiteral value: KeyPath) {
         
-        self = ._Attribute(value)
+        self = ._attribute(value)
+    }
+    
+    
+    // MARK: Equatable
+    
+    public static func == (lhs: SelectTerm, rhs: SelectTerm) -> Bool {
+        
+        switch (lhs, rhs) {
+            
+        case (._attribute(let keyPath1), ._attribute(let keyPath2)):
+            return keyPath1 == keyPath2
+            
+        case (._aggregate(let function1, let keyPath1, let alias1, let nativeType1),
+              ._aggregate(let function2, let keyPath2, let alias2, let nativeType2)):
+            return function1 == function2
+                && keyPath1 == keyPath2
+                && alias1 == alias2
+                && nativeType1 == nativeType2
+            
+        case (._identity(let alias1, let nativeType1), ._identity(let alias2, let nativeType2)):
+            return alias1 == alias2 && nativeType1 == nativeType2
+            
+        default:
+            return false
+        }
     }
     
     
@@ -254,13 +272,13 @@ public enum SelectTerm: StringLiteralConvertible, Hashable {
         
         switch self {
             
-        case ._Attribute(let keyPath):
+        case ._attribute(let keyPath):
             return 0 ^ keyPath.hashValue
             
-        case ._Aggregate(let function, let keyPath, let alias, let nativeType):
+        case ._aggregate(let function, let keyPath, let alias, let nativeType):
             return 1 ^ function.hashValue ^ keyPath.hashValue ^ alias.hashValue ^ nativeType.hashValue
             
-        case ._Identity(let alias, let nativeType):
+        case ._identity(let alias, let nativeType):
             return 3 ^ alias.hashValue ^ nativeType.hashValue
         }
     }
@@ -268,35 +286,9 @@ public enum SelectTerm: StringLiteralConvertible, Hashable {
     
     // MARK: Internal
     
-    case _Attribute(KeyPath)
-    case _Aggregate(function: String, keyPath: KeyPath, alias: String, nativeType: NSAttributeType)
-    case _Identity(alias: String, nativeType: NSAttributeType)
-}
-
-
-// MARK: - SelectTerm: Equatable
-
-@warn_unused_result
-public func == (lhs: SelectTerm, rhs: SelectTerm) -> Bool {
-    
-    switch (lhs, rhs) {
-        
-    case (._Attribute(let keyPath1), ._Attribute(let keyPath2)):
-        return keyPath1 == keyPath2
-        
-    case (._Aggregate(let function1, let keyPath1, let alias1, let nativeType1),
-        ._Aggregate(let function2, let keyPath2, let alias2, let nativeType2)):
-        return function1 == function2
-            && keyPath1 == keyPath2
-            && alias1 == alias2
-            && nativeType1 == nativeType2
-        
-    case (._Identity(let alias1, let nativeType1), ._Identity(let alias2, let nativeType2)):
-        return alias1 == alias2 && nativeType1 == nativeType2
-        
-    default:
-        return false
-    }
+    case _attribute(KeyPath)
+    case _aggregate(function: String, keyPath: KeyPath, alias: String, nativeType: NSAttributeType)
+    case _identity(alias: String, nativeType: NSAttributeType)
 }
 
 
@@ -308,15 +300,15 @@ public func == (lhs: SelectTerm, rhs: SelectTerm) -> Bool {
  You can bind the return type by specializing the initializer:
  ```
  let maximumAge = CoreStore.queryValue(
-     From(MyPersonEntity),
-     Select(.Maximum("age"))
+     From(),
+     Select(.maximum("age"))
  )
  ```
  or by casting the type of the return value:
  ```
  let maximumAge: Int = CoreStore.queryValue(
-     From(MyPersonEntity),
-     Select(.Maximum("age"))
+     From(),
+     Select(.maximum("age"))
  )
  ```
  Valid return types depend on the query:
@@ -330,13 +322,14 @@ public func == (lhs: SelectTerm, rhs: SelectTerm) -> Bool {
      - `Double`
      - `Float`
      - `String`
+     - `Date`
+     - `Data`
      - `NSNumber`
      - `NSString`
      - `NSDecimalNumber`
      - `NSDate`
      - `NSData`
      - `NSManagedObjectID`
-     - `NSString`
  - for `queryAttributes(...)` methods:
      - `NSDictionary`
  
@@ -371,11 +364,19 @@ public struct Select: Hashable {
     }
     
     
+    // MARK: Equatable
+    
+    public static func == (lhs: Select, rhs: Select) -> Bool {
+        
+        return lhs.selectTerms == rhs.selectTerms
+    }
+    
+    
     // MARK: Hashable
     
     public var hashValue: Int {
         
-        return self.selectTerms.map { $0.hashValue }.reduce(0, combine: ^)
+        return self.selectTerms.map { $0.hashValue }.reduce(0, ^)
     }
     
     
@@ -388,36 +389,27 @@ public extension Select where T: NSManagedObjectID {
     
     public init() {
         
-        self.init(.ObjectID())
+        self.init(.objectID())
     }
 }
 
 
-// MARK: - Select: Equatable
-
-@warn_unused_result
-public func == (lhs: Select, rhs: Select) -> Bool {
-    
-    return lhs.selectTerms == rhs.selectTerms
-}
-
-
 // MARK: - Bool: SelectValueResultType
 
 extension Bool: SelectValueResultType {
     
     public static var attributeType: NSAttributeType {
         
-        return .BooleanAttributeType
+        return .booleanAttributeType
     }
     
-    public static func fromResultObject(result: AnyObject) -> Bool? {
+    public static func fromResultObject(_ result: Any) -> Bool? {
         switch result {
             
         case let decimal as NSDecimalNumber:
             // iOS: NSDecimalNumber(string: "0.5").boolValue // true
             // OSX: NSDecimalNumber(string: "0.5").boolValue // false
-            return NSNumber(double: decimal.doubleValue).boolValue
+            return NSNumber(value: decimal.doubleValue).boolValue
             
         case let number as NSNumber:
             return number.boolValue
@@ -435,12 +427,12 @@ extension Int8: SelectValueResultType {
     
     public static var attributeType: NSAttributeType {
         
-        return .Integer64AttributeType
+        return .integer64AttributeType
     }
     
-    public static func fromResultObject(result: AnyObject) -> Int8? {
+    public static func fromResultObject(_ result: Any) -> Int8? {
         
-        guard let value = (result as? NSNumber)?.longLongValue else {
+        guard let value = (result as? NSNumber)?.int64Value else {
             
             return nil
         }
@@ -455,12 +447,12 @@ extension Int16: SelectValueResultType {
     
     public static var attributeType: NSAttributeType {
         
-        return .Integer64AttributeType
+        return .integer64AttributeType
     }
     
-    public static func fromResultObject(result: AnyObject) -> Int16? {
+    public static func fromResultObject(_ result: Any) -> Int16? {
         
-        guard let value = (result as? NSNumber)?.longLongValue else {
+        guard let value = (result as? NSNumber)?.int64Value else {
             
             return nil
         }
@@ -475,12 +467,12 @@ extension Int32: SelectValueResultType {
     
     public static var attributeType: NSAttributeType {
         
-        return .Integer64AttributeType
+        return .integer64AttributeType
     }
     
-    public static func fromResultObject(result: AnyObject) -> Int32? {
+    public static func fromResultObject(_ result: Any) -> Int32? {
         
-        guard let value = (result as? NSNumber)?.longLongValue else {
+        guard let value = (result as? NSNumber)?.int64Value else {
             
             return nil
         }
@@ -495,12 +487,12 @@ extension Int64: SelectValueResultType {
     
     public static var attributeType: NSAttributeType {
         
-        return .Integer64AttributeType
+        return .integer64AttributeType
     }
     
-    public static func fromResultObject(result: AnyObject) -> Int64? {
+    public static func fromResultObject(_ result: Any) -> Int64? {
         
-        return (result as? NSNumber)?.longLongValue
+        return (result as? NSNumber)?.int64Value
     }
 }
 
@@ -511,12 +503,12 @@ extension Int: SelectValueResultType {
     
     public static var attributeType: NSAttributeType {
         
-        return .Integer64AttributeType
+        return .integer64AttributeType
     }
     
-    public static func fromResultObject(result: AnyObject) -> Int? {
+    public static func fromResultObject(_ result: Any) -> Int? {
         
-        guard let value = (result as? NSNumber)?.longLongValue else {
+        guard let value = (result as? NSNumber)?.int64Value else {
             
             return nil
         }
@@ -531,10 +523,10 @@ extension Double: SelectValueResultType {
     
     public static var attributeType: NSAttributeType {
         
-        return .DoubleAttributeType
+        return .doubleAttributeType
     }
     
-    public static func fromResultObject(result: AnyObject) -> Double? {
+    public static func fromResultObject(_ result: Any) -> Double? {
         
         return (result as? NSNumber)?.doubleValue
     }
@@ -547,10 +539,10 @@ extension Float: SelectValueResultType {
     
     public static var attributeType: NSAttributeType {
         
-        return .FloatAttributeType
+        return .floatAttributeType
     }
     
-    public static func fromResultObject(result: AnyObject) -> Float? {
+    public static func fromResultObject(_ result: Any) -> Float? {
         
         return (result as? NSNumber)?.floatValue
     }
@@ -563,12 +555,44 @@ extension String: SelectValueResultType {
     
     public static var attributeType: NSAttributeType {
         
-        return .StringAttributeType
+        return .stringAttributeType
     }
     
-    public static func fromResultObject(result: AnyObject) -> String? {
+    public static func fromResultObject(_ result: Any) -> String? {
         
-        return result as? NSString as? String
+        return result as? String
+    }
+}
+
+
+// MARK: - Date: SelectValueResultType
+
+extension Date: SelectValueResultType {
+    
+    public static var attributeType: NSAttributeType {
+        
+        return .dateAttributeType
+    }
+    
+    public static func fromResultObject(_ result: Any) -> Date? {
+        
+        return result as? Date
+    }
+}
+
+
+// MARK: - Data: SelectValueResultType
+
+extension Data: SelectValueResultType {
+    
+    public static var attributeType: NSAttributeType {
+        
+        return .binaryDataAttributeType
+    }
+    
+    public static func fromResultObject(_ result: Any) -> Data? {
+        
+        return result as? Data
     }
 }
 
@@ -579,12 +603,12 @@ extension NSNumber: SelectValueResultType {
     
     public class var attributeType: NSAttributeType {
         
-        return .Integer64AttributeType
+        return .integer64AttributeType
     }
     
-    public class func fromResultObject(result: AnyObject) -> Self? {
+    public class func fromResultObject(_ result: Any) -> Self? {
         
-        func forceCast(object: AnyObject) -> T? {
+        func forceCast(_ object: Any) -> T? {
             
             return (object as? T)
         }
@@ -599,12 +623,12 @@ extension NSString: SelectValueResultType {
     
     public class var attributeType: NSAttributeType {
         
-        return .StringAttributeType
+        return .stringAttributeType
     }
     
-    public class func fromResultObject(result: AnyObject) -> Self? {
+    public class func fromResultObject(_ result: Any) -> Self? {
         
-        func forceCast(object: AnyObject) -> T? {
+        func forceCast(_ object: Any) -> T? {
             
             return (object as? T)
         }
@@ -619,12 +643,12 @@ extension NSDecimalNumber {
     
     public override class var attributeType: NSAttributeType {
         
-        return .DecimalAttributeType
+        return .decimalAttributeType
     }
     
-    public override class func fromResultObject(result: AnyObject) -> Self? {
+    public override class func fromResultObject(_ result: Any) -> Self? {
         
-        func forceCast(object: AnyObject) -> T? {
+        func forceCast(_ object: Any) -> T? {
             
             return (object as? T)
         }
@@ -637,14 +661,14 @@ extension NSDecimalNumber {
 
 extension NSDate: SelectValueResultType {
     
-    public class var attributeType: NSAttributeType {
+    public static var attributeType: NSAttributeType {
         
-        return .DateAttributeType
+        return .dateAttributeType
     }
     
-    public class func fromResultObject(result: AnyObject) -> Self? {
+    public class func fromResultObject(_ result: Any) -> Self? {
         
-        func forceCast(object: AnyObject) -> T? {
+        func forceCast(_ object: Any) -> T? {
             
             return (object as? T)
         }
@@ -657,14 +681,14 @@ extension NSDate: SelectValueResultType {
 
 extension NSData: SelectValueResultType {
     
-    public class var attributeType: NSAttributeType {
+    public static var attributeType: NSAttributeType {
         
-        return .BinaryDataAttributeType
+        return .binaryDataAttributeType
     }
     
-    public class func fromResultObject(result: AnyObject) -> Self? {
+    public class func fromResultObject(_ result: Any) -> Self? {
         
-        func forceCast(object: AnyObject) -> T? {
+        func forceCast(_ object: Any) -> T? {
             
             return (object as? T)
         }
@@ -679,12 +703,12 @@ extension NSManagedObjectID: SelectValueResultType {
     
     public class var attributeType: NSAttributeType {
         
-        return .ObjectIDAttributeType
+        return .objectIDAttributeType
     }
     
-    public class func fromResultObject(result: AnyObject) -> Self? {
+    public class func fromResultObject(_ result: Any) -> Self? {
         
-        func forceCast(object: AnyObject) -> T? {
+        func forceCast(_ object: Any) -> T? {
             
             return (object as? T)
         }
@@ -699,25 +723,25 @@ extension NSDictionary: SelectAttributesResultType {
     
     // MARK: SelectAttributesResultType
     
-    public class func fromResultObjects(result: [AnyObject]) -> [[NSString: AnyObject]] {
+    public class func fromResultObjects(_ result: [Any]) -> [[String: Any]] {
         
-        return result as! [[NSString: AnyObject]]
+        return result as! [[String: Any]]
     }
 }
 
 
 // MARK: - Internal
 
-internal extension CollectionType where Generator.Element == SelectTerm {
+internal extension Collection where Iterator.Element == SelectTerm {
     
-    internal func applyToFetchRequest(fetchRequest: NSFetchRequest, owner: T) {
+    internal func applyToFetchRequest(_ fetchRequest: NSFetchRequest, owner: T) {
         
         fetchRequest.includesPendingChanges = false
-        fetchRequest.resultType = .DictionaryResultType
+        fetchRequest.resultType = .dictionaryResultType
         
-        func attributeDescriptionForKeyPath(keyPath: String, inEntity entity: NSEntityDescription) -> NSAttributeDescription? {
+        func attributeDescription(for keyPath: String, in entity: NSEntityDescription) -> NSAttributeDescription? {
             
-            let components = keyPath.componentsSeparatedByString(".")
+            let components = keyPath.components(separatedBy: ".")
             switch components.count {
                 
             case 0:
@@ -731,39 +755,39 @@ internal extension CollectionType where Generator.Element == SelectTerm {
                     
                     return nil
                 }
-                return attributeDescriptionForKeyPath(
-                    components.dropFirst().joinWithSeparator("."),
-                    inEntity: relationship.entity
+                return attributeDescription(
+                    for: components.dropFirst().joined(separator: "."),
+                    in: relationship.entity
                 )
             }
         }
         
-        var propertiesToFetch = [AnyObject]()
+        var propertiesToFetch = [Any]()
         for term in self {
             
             switch term {
                 
-            case ._Attribute(let keyPath):
+            case ._attribute(let keyPath):
                 let entityDescription = fetchRequest.entity!
-                if let attributeDescription = attributeDescriptionForKeyPath(keyPath, inEntity: entityDescription) {
+                if let attributeDescription = attributeDescription(for: keyPath, in: entityDescription) {
                     
                     propertiesToFetch.append(attributeDescription)
                 }
                 else {
                     
                     CoreStore.log(
-                        .Warning,
+                        .warning,
                         message: "The key path \"\(keyPath)\" could not be resolved in entity \(cs_typeName(entityDescription.managedObjectClassName)) as an attribute and will be ignored by \(cs_typeName(owner)) query clause."
                     )
                 }
                 
-            case ._Aggregate(let function, let keyPath, let alias, let nativeType):
+            case ._aggregate(let function, let keyPath, let alias, let nativeType):
                 let entityDescription = fetchRequest.entity!
-                if let attributeDescription = attributeDescriptionForKeyPath(keyPath, inEntity: entityDescription) {
+                if let attributeDescription = attributeDescription(for: keyPath, in: entityDescription) {
                     
                     let expressionDescription = NSExpressionDescription()
                     expressionDescription.name = alias
-                    if nativeType == .UndefinedAttributeType {
+                    if nativeType == .undefinedAttributeType {
                         
                         expressionDescription.expressionResultType = attributeDescription.attributeType
                     }
@@ -780,17 +804,17 @@ internal extension CollectionType where Generator.Element == SelectTerm {
                 else {
                     
                     CoreStore.log(
-                        .Warning,
+                        .warning,
                         message: "The key path \"\(keyPath)\" could not be resolved in entity \(cs_typeName(entityDescription.managedObjectClassName)) as an attribute and will be ignored by \(cs_typeName(owner)) query clause."
                     )
                 }
                 
-            case ._Identity(let alias, let nativeType):
+            case ._identity(let alias, let nativeType):
                 let expressionDescription = NSExpressionDescription()
                 expressionDescription.name = alias
-                if nativeType == .UndefinedAttributeType {
+                if nativeType == .undefinedAttributeType {
                     
-                    expressionDescription.expressionResultType = .ObjectIDAttributeType
+                    expressionDescription.expressionResultType = .objectIDAttributeType
                 }
                 else {
                     
@@ -809,13 +833,13 @@ internal extension CollectionType where Generator.Element == SelectTerm {
         
         switch self.first! {
             
-        case ._Attribute(let keyPath):
+        case ._attribute(let keyPath):
             return keyPath
             
-        case ._Aggregate(_, _, let alias, _):
+        case ._aggregate(_, _, let alias, _):
             return alias
             
-        case ._Identity(let alias, _):
+        case ._identity(let alias, _):
             return alias
         }
     }
diff --git a/Sources/Fetching and Querying/Concrete Clauses/Tweak.swift b/Sources/Fetching and Querying/Concrete Clauses/Tweak.swift
index bf4b870..108be78 100644
--- a/Sources/Fetching and Querying/Concrete Clauses/Tweak.swift	
+++ b/Sources/Fetching and Querying/Concrete Clauses/Tweak.swift	
@@ -34,7 +34,7 @@ import CoreData
  Sample usage:
  ```
  let employees = transaction.fetchAll(
-     From(MyPersonEntity),
+     From(),
      Tweak { (fetchRequest) -> Void in
          fetchRequest.includesPendingChanges = false
          fetchRequest.fetchLimit = 5
@@ -47,7 +47,7 @@ public struct Tweak: FetchClause, QueryClause, DeleteClause {
     /**
      The block to customize the `NSFetchRequest`
      */
-    public let closure: (fetchRequest: NSFetchRequest) -> Void
+    public let closure: (_ fetchRequest: NSFetchRequest) -> Void
     
     /**
      Initializes a `Tweak` clause with a closure where the `NSFetchRequest` may be configured.
@@ -55,7 +55,7 @@ public struct Tweak: FetchClause, QueryClause, DeleteClause {
      - Important: `Tweak`'s closure is executed only just before the fetch occurs, so make sure that any values captured by the closure is not prone to race conditions. Also, some utilities (such as `ListMonitor`s) may keep `FetchClause`s in memory and may thus introduce retain cycles if reference captures are not handled properly.
      - parameter closure: the block to customize the `NSFetchRequest`
      */
-    public init(_ closure: (fetchRequest: NSFetchRequest) -> Void) {
+    public init(_ closure: @escaping (_ fetchRequest: NSFetchRequest) -> Void) {
         
         self.closure = closure
     }
@@ -63,8 +63,8 @@ public struct Tweak: FetchClause, QueryClause, DeleteClause {
     
     // MARK: FetchClause, QueryClause, DeleteClause
     
-    public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
+    public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) {
         
-        self.closure(fetchRequest: fetchRequest)
+        self.closure(fetchRequest as! NSFetchRequest)
     }
 }
diff --git a/Sources/Fetching and Querying/Concrete Clauses/Where.swift b/Sources/Fetching and Querying/Concrete Clauses/Where.swift
index 46e04be..75fc7f6 100644
--- a/Sources/Fetching and Querying/Concrete Clauses/Where.swift	
+++ b/Sources/Fetching and Querying/Concrete Clauses/Where.swift	
@@ -27,19 +27,19 @@ import Foundation
 import CoreData
 
 
-public func &&(left: Where, right: Where) -> Where {
+public func && (left: Where, right: Where) -> Where {
     
-    return Where(NSCompoundPredicate(type: .AndPredicateType, subpredicates: [left.predicate, right.predicate]))
+    return Where(NSCompoundPredicate(type: .and, subpredicates: [left.predicate, right.predicate]))
 }
 
-public func ||(left: Where, right: Where) -> Where {
+public func || (left: Where, right: Where) -> Where {
     
-    return Where(NSCompoundPredicate(type: .OrPredicateType, subpredicates: [left.predicate, right.predicate]))
+    return Where(NSCompoundPredicate(type: .or, subpredicates: [left.predicate, right.predicate]))
 }
 
-public prefix func !(clause: Where) -> Where {
+public prefix func ! (clause: Where) -> Where {
     
-    return Where(NSCompoundPredicate(type: .NotPredicateType, subpredicates: [clause.predicate]))
+    return Where(NSCompoundPredicate(type: .not, subpredicates: [clause.predicate]))
 }
 
 
@@ -79,7 +79,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
      - parameter format: the format string for the predicate
      - parameter args: the arguments for `format`
      */
-    public init(_ format: String, _ args: NSObject...) {
+    public init(_ format: String, _ args: Any...) {
         
         self.init(NSPredicate(format: format, argumentArray: args))
     }
@@ -90,7 +90,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
      - parameter format: the format string for the predicate
      - parameter argumentArray: the arguments for `format`
      */
-    public init(_ format: String, argumentArray: [NSObject]?) {
+    public init(_ format: String, argumentArray: [Any]?) {
         
         self.init(NSPredicate(format: format, argumentArray: argumentArray))
     }
@@ -101,7 +101,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
      - parameter keyPath: the keyPath to compare with
      - parameter value: the arguments for the `==` operator
      */
-    public init(_ keyPath: KeyPath, isEqualTo value: NSObject?) {
+    public init(_ keyPath: KeyPath, isEqualTo value: Any?) {
         
         self.init(value == nil
             ? NSPredicate(format: "\(keyPath) == nil")
@@ -114,7 +114,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
      - parameter keyPath: the keyPath to compare with
      - parameter list: the array to check membership of
      */
-    public init(_ keyPath: KeyPath, isMemberOf list: [NSObject]) {
+    public init(_ keyPath: KeyPath, isMemberOf list: [Any]) {
         
         self.init(NSPredicate(format: "\(keyPath) IN %@", list))
     }
@@ -125,7 +125,7 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
      - parameter keyPath: the keyPath to compare with
      - parameter list: the sequence to check membership of
      */
-    public init(_ keyPath: KeyPath, isMemberOf list: S) {
+    public init(_ keyPath: KeyPath, isMemberOf list: S) where S.Iterator.Element: Any {
         
         self.init(NSPredicate(format: "\(keyPath) IN %@", Array(list) as NSArray))
     }
@@ -143,13 +143,13 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
     
     // MARK: FetchClause, QueryClause, DeleteClause
     
-    public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
+    public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) {
         
-        if let predicate = fetchRequest.predicate where predicate != self.predicate {
+        if let predicate = fetchRequest.predicate, predicate != self.predicate {
             
             CoreStore.log(
-                .Warning,
-                message: "An existing predicate for the \(cs_typeName(NSFetchRequest)) was overwritten by \(cs_typeName(self)) query clause."
+                .warning,
+                message: "An existing predicate for the \(cs_typeName(fetchRequest)) was overwritten by \(cs_typeName(self)) query clause."
             )
         }
         
@@ -157,6 +157,14 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
     }
     
     
+    // MARK: Equatable
+    
+    public static func == (lhs: Where, rhs: Where) -> Bool {
+        
+        return lhs.predicate == rhs.predicate
+    }
+    
+    
     // MARK: Hashable
     
     public var hashValue: Int {
@@ -164,12 +172,3 @@ public struct Where: FetchClause, QueryClause, DeleteClause, Hashable {
         return self.predicate.hashValue
     }
 }
-
-
-// MARK: - Where: Equatable
-
-@warn_unused_result
-public func == (lhs: Where, rhs: Where) -> Bool {
-    
-    return lhs.predicate == rhs.predicate
-}
diff --git a/Sources/Fetching and Querying/CoreStore+Querying.swift b/Sources/Fetching and Querying/CoreStore+Querying.swift
index 566c680..18ff1d0 100644
--- a/Sources/Fetching and Querying/CoreStore+Querying.swift	
+++ b/Sources/Fetching and Querying/CoreStore+Querying.swift	
@@ -37,8 +37,7 @@ public extension CoreStore {
      - parameter object: a reference to the object created/fetched outside the `DataStack`
      - returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
      */
-    @warn_unused_result
-    public static func fetchExisting(object: T) -> T? {
+    public static func fetchExisting(_ object: T) -> T? {
         
         return self.defaultStack.fetchExisting(object)
     }
@@ -49,8 +48,7 @@ public extension CoreStore {
      - parameter objectID: the `NSManagedObjectID` for the object
      - returns: the `NSManagedObject` instance if the object exists in the `DataStack`, or `nil` if not found.
      */
-    @warn_unused_result
-    public static func fetchExisting(objectID: NSManagedObjectID) -> T? {
+    public static func fetchExisting(_ objectID: NSManagedObjectID) -> T? {
         
         return self.defaultStack.fetchExisting(objectID)
     }
@@ -61,8 +59,7 @@ public extension CoreStore {
      - parameter objects: an array of `NSManagedObject`s created/fetched outside the `DataStack`
      - returns: the `NSManagedObject` array for objects that exists in the `DataStack`
      */
-    @warn_unused_result
-    public static func fetchExisting(objects: S) -> [T] {
+    public static func fetchExisting(_ objects: S) -> [T] where S.Iterator.Element == T {
         
         return self.defaultStack.fetchExisting(objects)
     }
@@ -73,8 +70,7 @@ public extension CoreStore {
      - parameter objectIDs: the `NSManagedObjectID` array for the objects
      - returns: the `NSManagedObject` array for objects that exists in the `DataStack`
      */
-    @warn_unused_result
-    public static func fetchExisting(objectIDs: S) -> [T] {
+    public static func fetchExisting(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
         
         return self.defaultStack.fetchExisting(objectIDs)
     }
@@ -86,8 +82,7 @@ public extension CoreStore {
      - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
      */
-    @warn_unused_result
-    public static func fetchOne(from: From, _ fetchClauses: FetchClause...) -> T? {
+    public static func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? {
         
         return self.defaultStack.fetchOne(from, fetchClauses)
     }
@@ -99,8 +94,7 @@ public extension CoreStore {
      - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
      */
-    @warn_unused_result
-    public static func fetchOne(from: From, _ fetchClauses: [FetchClause]) -> T? {
+    public static func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? {
         
         return self.defaultStack.fetchOne(from, fetchClauses)
     }
@@ -112,8 +106,7 @@ public extension CoreStore {
      - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
      */
-    @warn_unused_result
-    public static func fetchAll(from: From, _ fetchClauses: FetchClause...) -> [T]? {
+    public static func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? {
         
         return self.defaultStack.fetchAll(from, fetchClauses)
     }
@@ -125,8 +118,7 @@ public extension CoreStore {
      - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
      */
-    @warn_unused_result
-    public static func fetchAll(from: From, _ fetchClauses: [FetchClause]) -> [T]? {
+    public static func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? {
         
         return self.defaultStack.fetchAll(from, fetchClauses)
     }
@@ -138,8 +130,7 @@ public extension CoreStore {
      - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
      */
-    @warn_unused_result
-    public static func fetchCount(from: From, _ fetchClauses: FetchClause...) -> Int? {
+    public static func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? {
         
         return self.defaultStack.fetchCount(from, fetchClauses)
     }
@@ -151,8 +142,7 @@ public extension CoreStore {
      - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
      */
-    @warn_unused_result
-    public static func fetchCount(from: From, _ fetchClauses: [FetchClause]) -> Int? {
+    public static func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? {
         
         return self.defaultStack.fetchCount(from, fetchClauses)
     }
@@ -164,8 +154,7 @@ public extension CoreStore {
      - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
      */
-    @warn_unused_result
-    public static func fetchObjectID(from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
+    public static func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
         
         return self.defaultStack.fetchObjectID(from, fetchClauses)
     }
@@ -177,8 +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(from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
+    public static func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
         
         return self.defaultStack.fetchObjectID(from, fetchClauses)
     }
@@ -190,8 +178,7 @@ public extension CoreStore {
      - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
      */
-    @warn_unused_result
-    public static func fetchObjectIDs(from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
+    public static func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
         
         return self.defaultStack.fetchObjectIDs(from, fetchClauses)
     }
@@ -203,8 +190,7 @@ public extension CoreStore {
      - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
      */
-    @warn_unused_result
-    public static func fetchObjectIDs(from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
+    public static func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
         
         return self.defaultStack.fetchObjectIDs(from, fetchClauses)
     }
@@ -219,8 +205,7 @@ public extension CoreStore {
      - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter.
      */
-    @warn_unused_result
-    public static func queryValue(from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? {
+    public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? {
         
         return self.defaultStack.queryValue(from, selectClause, queryClauses)
     }
@@ -235,8 +220,7 @@ public extension CoreStore {
      - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter.
      */
-    @warn_unused_result
-    public static func queryValue(from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? {
+    public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? {
         
         return self.defaultStack.queryValue(from, selectClause, queryClauses)
     }
@@ -251,8 +235,7 @@ public extension CoreStore {
      - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter.
      */
-    @warn_unused_result
-    public static func queryAttributes(from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
+    public static func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? {
         
         return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
     }
@@ -267,8 +250,7 @@ public extension CoreStore {
      - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter.
      */
-    @warn_unused_result
-    public static func queryAttributes(from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
+    public static func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
         
         return self.defaultStack.queryAttributes(from, selectClause, queryClauses)
     }
diff --git a/Sources/Fetching and Querying/DataStack+Querying.swift b/Sources/Fetching and Querying/DataStack+Querying.swift
index 9f13947..d9a771a 100644
--- a/Sources/Fetching and Querying/DataStack+Querying.swift	
+++ b/Sources/Fetching and Querying/DataStack+Querying.swift	
@@ -25,14 +25,13 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - DataStack
 
-public extension DataStack {
+extension DataStack: FetchableSource, QueryableSource {
+    
+    // MARK: FetchableSource
     
     /**
      Fetches the `NSManagedObject` instance in the `DataStack`'s context from a reference created from a transaction or from a different managed object context.
@@ -40,17 +39,9 @@ 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(object: T) -> T? {
+    public func fetchExisting(_ object: T) -> T? {
         
-        do {
-            
-            return (try self.mainContext.existingObjectWithID(object.objectID) as! T)
-        }
-        catch _ {
-            
-            return nil
-        }
+        return self.mainContext.fetchExisting(object)
     }
     
     /**
@@ -59,17 +50,9 @@ 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(objectID: NSManagedObjectID) -> T? {
+    public func fetchExisting(_ objectID: NSManagedObjectID) -> T? {
         
-        do {
-            
-            return (try self.mainContext.existingObjectWithID(objectID) as! T)
-        }
-        catch _ {
-            
-            return nil
-        }
+        return self.mainContext.fetchExisting(objectID)
     }
     
     /**
@@ -78,10 +61,9 @@ 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`
      */
-    @warn_unused_result
-    public func fetchExisting(objects: S) -> [T] {
+    public func fetchExisting(_ objects: S) -> [T] where S.Iterator.Element == T {
         
-        return objects.flatMap { (try? self.mainContext.existingObjectWithID($0.objectID)) as? T }
+        return self.mainContext.fetchExisting(objects)
     }
     
     /**
@@ -90,10 +72,9 @@ public extension DataStack {
      - parameter objectIDs: the `NSManagedObjectID` array for the objects
      - returns: the `NSManagedObject` array for objects that exists in the `DataStack`
      */
-    @warn_unused_result
-    public func fetchExisting(objectIDs: S) -> [T] {
+    public func fetchExisting(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
         
-        return objectIDs.flatMap { (try? self.mainContext.existingObjectWithID($0)) as? T }
+        return self.mainContext.fetchExisting(objectIDs)
     }
     
     /**
@@ -103,11 +84,10 @@ 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(from: From, _ fetchClauses: FetchClause...) -> T? {
+    public func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchOne(from, fetchClauses)
@@ -120,11 +100,10 @@ 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(from: From, _ fetchClauses: [FetchClause]) -> T? {
+    public func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchOne(from, fetchClauses)
@@ -137,11 +116,10 @@ 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(from: From, _ fetchClauses: FetchClause...) -> [T]? {
+    public func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchAll(from, fetchClauses)
@@ -154,11 +132,10 @@ 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(from: From, _ fetchClauses: [FetchClause]) -> [T]? {
+    public func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchAll(from, fetchClauses)
@@ -171,11 +148,10 @@ 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(from: From, _ fetchClauses: FetchClause...) -> Int? {
+    public func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchCount(from, fetchClauses)
@@ -188,11 +164,10 @@ 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(from: From, _ fetchClauses: [FetchClause]) -> Int? {
+    public func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchCount(from, fetchClauses)
@@ -205,11 +180,10 @@ 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(from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
+    public func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchObjectID(from, fetchClauses)
@@ -222,11 +196,10 @@ 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(from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
+    public func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchObjectID(from, fetchClauses)
@@ -239,11 +212,10 @@ 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(from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
+    public func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchObjectIDs(from, fetchClauses)
@@ -256,16 +228,18 @@ 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(from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
+    public func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.fetchObjectIDs(from, fetchClauses)
     }
     
+    
+    // MARK: QueryableSource
+    
     /**
      Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
      
@@ -276,11 +250,10 @@ 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` parameter.
      */
-    @warn_unused_result
-    public func queryValue(from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? {
+    public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to query from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.queryValue(from, selectClause, queryClauses)
@@ -296,11 +269,10 @@ 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` parameter.
      */
-    @warn_unused_result
-    public func queryValue(from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? {
+    public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to query from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.queryValue(from, selectClause, queryClauses)
@@ -316,11 +288,10 @@ 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` parameter.
      */
-    @warn_unused_result
-    public func queryAttributes(from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
+    public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to query from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.queryAttributes(from, selectClause, queryClauses)
@@ -336,13 +307,23 @@ 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` parameter.
      */
-    @warn_unused_result
-    public func queryAttributes(from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
+    public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to query from a \(cs_typeName(self)) outside the main thread."
         )
         return self.mainContext.queryAttributes(from, selectClause, queryClauses)
     }
+    
+    
+    // MARK: FetchableSource, QueryableSource
+    
+    /**
+     The internal `NSManagedObjectContext` managed by this instance. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases.
+     */
+    public func internalContext() -> NSManagedObjectContext {
+        
+        return self.mainContext
+    }
 }
diff --git a/Sources/Fetching and Querying/FetchableSource.swift b/Sources/Fetching and Querying/FetchableSource.swift
new file mode 100644
index 0000000..0252d36
--- /dev/null
+++ b/Sources/Fetching and Querying/FetchableSource.swift	
@@ -0,0 +1,163 @@
+//
+//  FetchableSource.swift
+//  CoreStore
+//
+//  Copyright © 2016 John Rommel Estropia
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in all
+//  copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+//  SOFTWARE.
+//
+
+import Foundation
+import CoreData
+
+
+// MARK: - FetchableSource
+
+/**
+ Encapsulates containers which manages an internal `NSManagedObjectContext`, such as `DataStack`s and transactions, that can be used for fetching objects. CoreStore provides implementations for this protocol and should be used as a read-only abstraction.
+ */
+public protocol FetchableSource: class {
+    
+    /**
+     Fetches the `NSManagedObject` instance in the `FetchableSource`'s context from a reference created from another managed object context.
+     
+     - parameter object: a reference to the object created/fetched outside the `FetchableSource`'s context
+     - returns: the `NSManagedObject` instance if the object exists in the `FetchableSource`'s context, or `nil` if not found.
+     */
+    func fetchExisting(_ object: T) -> T?
+    
+    /**
+     Fetches the `NSManagedObject` instance in the `FetchableSource`'s context from an `NSManagedObjectID`.
+     
+     - parameter objectID: the `NSManagedObjectID` for the object
+     - returns: the `NSManagedObject` instance if the object exists in the `FetchableSource`, or `nil` if not found.
+     */
+    func fetchExisting(_ objectID: NSManagedObjectID) -> T?
+    
+    /**
+     Fetches the `NSManagedObject` instances in the `FetchableSource`'s context from references created from another managed object context.
+
+     - parameter objects: an array of `NSManagedObject`s created/fetched outside the `FetchableSource`'s context
+     - returns: the `NSManagedObject` array for objects that exists in the `FetchableSource`
+     */
+    func fetchExisting(_ objects: S) -> [T] where S.Iterator.Element == T
+
+    /**
+     Fetches the `NSManagedObject` instances in the `FetchableSource`'s context from a list of `NSManagedObjectID`.
+
+     - parameter objectIDs: the `NSManagedObjectID` array for the objects
+     - returns: the `NSManagedObject` array for objects that exists in the `FetchableSource`'s context
+     */
+    func fetchExisting(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID
+
+    /**
+     Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
+     */
+    func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T?
+
+    /**
+     Fetches the first `NSManagedObject` instance that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the first `NSManagedObject` instance that satisfies the specified `FetchClause`s
+     */
+    func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T?
+
+    /**
+     Fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
+     */
+    func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]?
+
+    /**
+     Fetches all `NSManagedObject` instances that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: all `NSManagedObject` instances that satisfy the specified `FetchClause`s
+     */
+    func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]?
+
+    /**
+     Fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
+     */
+    func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int?
+
+    /**
+     Fetches the number of `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the number `NSManagedObject`s that satisfy the specified `FetchClause`s
+     */
+    func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int?
+
+    /**
+     Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
+     */
+    func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID?
+
+    /**
+     Fetches the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `FetchClause`s
+     */
+    func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID?
+
+    /**
+     Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
+     */
+    func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]?
+
+    /**
+     Fetches the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter fetchClauses: a series of `FetchClause` instances for the fetch request. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
+     - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `FetchClause`s
+     */
+    func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]?
+    
+    /**
+     The internal `NSManagedObjectContext` managed by this `FetchableSource`. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases.
+     */
+    func internalContext() -> NSManagedObjectContext
+}
diff --git a/Sources/Fetching and Querying/Protocol Clauses/ClauseTypes.swift b/Sources/Fetching and Querying/Protocol Clauses/ClauseTypes.swift
index 95e61f9..df207bb 100644
--- a/Sources/Fetching and Querying/Protocol Clauses/ClauseTypes.swift	
+++ b/Sources/Fetching and Querying/Protocol Clauses/ClauseTypes.swift	
@@ -34,7 +34,7 @@ import CoreData
  */
 public protocol FetchClause {
     
-    func applyToFetchRequest(fetchRequest: NSFetchRequest)
+    func applyToFetchRequest(_ fetchRequest: NSFetchRequest)
 }
 
 
@@ -45,7 +45,7 @@ public protocol FetchClause {
  */
 public protocol QueryClause {
     
-    func applyToFetchRequest(fetchRequest: NSFetchRequest)
+    func applyToFetchRequest(_ fetchRequest: NSFetchRequest)
 }
 
 
@@ -56,5 +56,5 @@ public protocol QueryClause {
  */
 public protocol DeleteClause {
     
-    func applyToFetchRequest(fetchRequest: NSFetchRequest)
+    func applyToFetchRequest(_ fetchRequest: NSFetchRequest)
 }
diff --git a/Sources/Fetching and Querying/QueryableSource.swift b/Sources/Fetching and Querying/QueryableSource.swift
new file mode 100644
index 0000000..0c9529e
--- /dev/null
+++ b/Sources/Fetching and Querying/QueryableSource.swift	
@@ -0,0 +1,89 @@
+//
+//  QueryableSource.swift
+//  CoreStore
+//
+//  Copyright © 2016 John Rommel Estropia
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in all
+//  copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+//  SOFTWARE.
+//
+
+import Foundation
+import CoreData
+
+
+// MARK: - QueryableSource
+
+/**
+ Encapsulates containers which manages an internal `NSManagedObjectContext`, such as `DataStack`s and transactions, that can be used for querying values. CoreStore provides implementations for this protocol and should be used as a read-only abstraction.
+ */
+public protocol QueryableSource: class {
+    
+    /**
+     Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
+
+     A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type.
+     - 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` parameter.
+     */
+    func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U?
+
+    /**
+     Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
+
+     A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type.
+     - 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` parameter.
+     */
+    func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U?
+
+    /**
+     Queries a dictionary of attribute values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
+
+     A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type.
+     - 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` parameter.
+     */
+    func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]?
+
+    /**
+     Queries a dictionary of attribute values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses.
+
+     A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result.
+
+     - parameter from: a `From` clause indicating the entity type
+     - parameter selectClause: a `Select` clause indicating the properties to fetch, and with the generic type indicating the return type.
+     - 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` parameter.
+     */
+    func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]?
+    
+    /**
+     The internal `NSManagedObjectContext` managed by this `QueryableSource`. Using this context directly should typically be avoided, and is provided by CoreStore only for extremely specialized cases.
+     */
+    func internalContext() -> NSManagedObjectContext
+}
diff --git a/Sources/Importing/BaseDataTransaction+Importing.swift b/Sources/Importing/BaseDataTransaction+Importing.swift
index 61ac229..45ccdf4 100644
--- a/Sources/Importing/BaseDataTransaction+Importing.swift
+++ b/Sources/Importing/BaseDataTransaction+Importing.swift
@@ -36,27 +36,29 @@ public extension BaseDataTransaction {
      
      - parameter into: an `Into` clause specifying the entity type
      - parameter source: the object to import values from
-     - throws: an `ErrorType` thrown from any of the `ImportableObject` methods
+     - throws: an `Error` thrown from any of the `ImportableObject` methods
      - returns: the created `ImportableObject` instance, or `nil` if the import was ignored
      */
-    public func importObject(
-        into: Into,
-        source: T.ImportSource) throws -> T? {
+    public func importObject(
+        _ into: Into,
+        source: T.ImportSource) throws -> T? where T: NSManagedObject, T: ImportableObject {
             
             CoreStore.assert(
                 self.isRunningInAllowedQueue(),
                 "Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
             )
-            
-            return try cs_autoreleasepool {
+        
+            return try autoreleasepool {
                 
-                guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
+                let entityType = into.entityClass as! T.Type
+                
+                guard entityType.shouldInsert(from: source, in: self) else {
                     
                     return nil
                 }
                 
                 let object = self.create(into)
-                try object.didInsertFromImportSource(source, inTransaction: self)
+                try object.didInsert(from: source, in: self)
                 return object
             }
     }
@@ -66,25 +68,25 @@ public extension BaseDataTransaction {
      
      - parameter object: the `NSManagedObject` to update
      - parameter source: the object to import values from
-     - throws: an `ErrorType` thrown from any of the `ImportableObject` methods
+     - throws: an `Error` thrown from any of the `ImportableObject` methods
      */
-    public func importObject(
-        object: T,
-        source: T.ImportSource) throws {
+    public func importObject(
+        _ object: T,
+        source: T.ImportSource) throws where T: NSManagedObject, T: ImportableObject {
             
             CoreStore.assert(
                 self.isRunningInAllowedQueue(),
                 "Attempted to import an object of type \(cs_typeName(object)) outside the transaction's designated queue."
             )
             
-            try cs_autoreleasepool {
-                
-                guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
+            try autoreleasepool {
+              
+                let entityType = type(of: object)
+                guard entityType.shouldInsert(from: source, in: self) else {
                     
                     return
                 }
-                
-                try object.didInsertFromImportSource(source, inTransaction: self)
+                try object.didInsert(from: source, in: self)
             }
     }
     
@@ -93,31 +95,31 @@ public extension BaseDataTransaction {
      
      - parameter into: an `Into` clause specifying the entity type
      - parameter sourceArray: the array of objects to import values from
-     - throws: an `ErrorType` thrown from any of the `ImportableObject` methods
+     - throws: an `Error` thrown from any of the `ImportableObject` methods
      - returns: the array of created `ImportableObject` instances
      */
-    public func importObjects(
-        into: Into,
-        sourceArray: S) throws -> [T] {
+    public func importObjects(
+        _ into: Into,
+        sourceArray: S) throws -> [T] where T: NSManagedObject, T: ImportableObject, S.Iterator.Element == T.ImportSource {
             
             CoreStore.assert(
                 self.isRunningInAllowedQueue(),
                 "Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
             )
             
-            return try cs_autoreleasepool {
+            return try autoreleasepool {
                 
                 return try sourceArray.flatMap { (source) -> T? in
-                    
-                    guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
+                  
+                    let entityType = into.entityClass as! T.Type
+                    guard entityType.shouldInsert(from: source, in: self) else {
                         
                         return nil
                     }
-                    
-                    return try cs_autoreleasepool {
+                    return try autoreleasepool {
                         
                         let object = self.create(into)
-                        try object.didInsertFromImportSource(source, inTransaction: self)
+                        try object.didInsert(from: source, in: self)
                         return object
                     }
                 }
@@ -129,46 +131,45 @@ public extension BaseDataTransaction {
      
      - parameter into: an `Into` clause specifying the entity type
      - parameter source: the object to import values from
-     - throws: an `ErrorType` thrown from any of the `ImportableUniqueObject` methods
+     - throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
      - returns: the created/updated `ImportableUniqueObject` instance, or `nil` if the import was ignored
      */
-    public func importUniqueObject(
-        into: Into,
-        source: T.ImportSource) throws -> T?  {
+    public func importUniqueObject(
+        _ into: Into,
+        source: T.ImportSource) throws -> T? where T: NSManagedObject, T: ImportableUniqueObject  {
             
             CoreStore.assert(
                 self.isRunningInAllowedQueue(),
                 "Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
             )
             
-            return try cs_autoreleasepool {
-                
-                let uniqueIDKeyPath = T.uniqueIDKeyPath
-                guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else {
+            return try autoreleasepool {
+              
+                let entityType = into.entityClass as! T.Type
+                let uniqueIDKeyPath = entityType.uniqueIDKeyPath
+                guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
                     
                     return nil
                 }
                 
-                if let object = self.fetchOne(From(T), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
+                if let object = self.fetchOne(From(entityType), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
                     
-                    guard T.shouldUpdateFromImportSource(source, inTransaction: self) else {
+                    guard entityType.shouldUpdate(from: source, in: self) else {
                         
                         return nil
                     }
-                    
-                    try object.updateFromImportSource(source, inTransaction: self)
+                    try object.update(from: source, in: self)
                     return object
                 }
                 else {
                     
-                    guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
+                    guard entityType.shouldInsert(from: source, in: self) else {
                         
                         return nil
                     }
-                    
                     let object = self.create(into)
                     object.uniqueIDValue = uniqueIDValue
-                    try object.didInsertFromImportSource(source, inTransaction: self)
+                    try object.didInsert(from: source, in: self)
                     return object
                 }
             }
@@ -176,79 +177,79 @@ public extension BaseDataTransaction {
     
     /**
      Updates existing `ImportableUniqueObject`s or creates them by importing from the specified array of import sources.
-     - Warning: While the array returned from `importUniqueObjects(...)` correctly maps to the order of `sourceArray`, the order of objects called with `ImportableUniqueObject` methods is arbitrary. Do not make assumptions that any particular object will be imported ahead or after another object.
+     `ImportableUniqueObject` methods are called on the objects in the same order as they are in the `sourceArray`, and are returned in an array with that same order.
+     - Warning: If `sourceArray` contains multiple import sources with same ID, no merging will occur and ONLY THE LAST duplicate will be imported.
      
      - parameter into: an `Into` clause specifying the entity type
      - parameter sourceArray: the array of objects to import values from
      - parameter preProcess: a closure that lets the caller tweak the internal `UniqueIDType`-to-`ImportSource` mapping to be used for importing. Callers can remove from/add to/update `mapping` and return the updated array from the closure.
-     - throws: an `ErrorType` thrown from any of the `ImportableUniqueObject` methods
+     - throws: an `Error` thrown from any of the `ImportableUniqueObject` methods
      - returns: the array of created/updated `ImportableUniqueObject` instances
      */
-    public func importUniqueObjects(
-        into: Into,
+    public func importUniqueObjects(
+        _ into: Into,
         sourceArray: S,
-        @noescape preProcess: (mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource] = { $0 }) throws -> [T] {
+        preProcess: @escaping (_ mapping: [T.UniqueIDType: T.ImportSource]) throws -> [T.UniqueIDType: T.ImportSource] = { $0 }) throws -> [T] where T: NSManagedObject, T: ImportableUniqueObject, S.Iterator.Element == T.ImportSource {
             
             CoreStore.assert(
                 self.isRunningInAllowedQueue(),
                 "Attempted to import an object of type \(cs_typeName(into.entityClass)) outside the transaction's designated queue."
             )
             
-            return try cs_autoreleasepool {
-                
-                var mapping = Dictionary()
-                let sortedIDs = try cs_autoreleasepool {
-                    
+            return try autoreleasepool {
+              
+                let entityType = into.entityClass as! T.Type
+                var importSourceByID = Dictionary()
+                let sortedIDs = try autoreleasepool {
+                  
                     return try sourceArray.flatMap { (source) -> T.UniqueIDType? in
                         
-                        guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else {
+                        guard let uniqueIDValue = try entityType.uniqueID(from: source, in: self) else {
                             
                             return nil
                         }
-                        
-                        mapping[uniqueIDValue] = source
+                        importSourceByID[uniqueIDValue] = source // effectively replaces duplicate with the latest
                         return uniqueIDValue
                     }
                 }
                 
-                mapping = try cs_autoreleasepool { try preProcess(mapping: mapping) }
-                
-                var objects = Dictionary()
-                for object in self.fetchAll(From(T), Where(T.uniqueIDKeyPath, isMemberOf: sortedIDs)) ?? [] {
+                importSourceByID = try autoreleasepool { try preProcess(importSourceByID) }
+
+                var existingObjectsByID = Dictionary()
+                self.fetchAll(From(entityType), Where(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))?
+                    .forEach { existingObjectsByID[$0.uniqueIDValue] = $0 }
+              
+                var processedObjectIDs = Set()
+                var result = [T]()
+              
+                for objectID in sortedIDs where !processedObjectIDs.contains(objectID) {
                     
-                    try cs_autoreleasepool {
+                    guard let source = importSourceByID[objectID] else {
                         
-                        let uniqueIDValue = object.uniqueIDValue
-                        
-                        guard let source = mapping.removeValueForKey(uniqueIDValue)
-                            where T.shouldUpdateFromImportSource(source, inTransaction: self) else {
+                        continue
+                    }
+                    try autoreleasepool {
+
+                        if let object = existingObjectsByID[objectID] {
+                            
+                            guard entityType.shouldUpdate(from: source, in: self) else {
                                 
                                 return
+                            }
+                            try object.update(from: source, in: self)
+                            result.append(object)
                         }
-                        
-                        try object.updateFromImportSource(source, inTransaction: self)
-                        objects[uniqueIDValue] = object
-                    }
-                }
-                
-                for (uniqueIDValue, source) in mapping {
-                    
-                    try cs_autoreleasepool {
-                        
-                        guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
+                        else if entityType.shouldInsert(from: source, in: self) {
                             
-                            return
+                            let object = self.create(into)
+                            object.uniqueIDValue = objectID
+                            try object.didInsert(from: source, in: self)
+                            result.append(object)
                         }
-                        
-                        let object = self.create(into)
-                        object.uniqueIDValue = uniqueIDValue
-                        try object.didInsertFromImportSource(source, inTransaction: self)
-                        
-                        objects[uniqueIDValue] = object
+                        processedObjectIDs.insert(objectID)
                     }
                 }
-                
-                return sortedIDs.flatMap { objects[$0] }
+                return result
             }
     }
 }
diff --git a/Sources/Importing/ImportableObject.swift b/Sources/Importing/ImportableObject.swift
index 7570f32..2dcd018 100644
--- a/Sources/Importing/ImportableObject.swift
+++ b/Sources/Importing/ImportableObject.swift
@@ -40,7 +40,7 @@ import CoreData
  CoreStore.beginAsynchronous { (transaction) -> Void in
      let json: NSDictionary = // ...
      let person = try! transaction.importObject(
-         Into(MyPersonEntity),
+         Into(),
          source: json
      )
      // ...
@@ -62,15 +62,24 @@ public protocol ImportableObject: class {
      - 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
+    static func shouldInsert(from source: ImportSource, in 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
+     */
+    func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws
+    
+    
+    // MARK: Deprecated
+    
+    @available(*, deprecated: 3.0.0, renamed: "shouldInsert(from:in:)")
+    static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
+    
+    @available(*, deprecated: 3.0.0, renamed: "didInsert(from:in:)")
+    func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
 }
 
 
@@ -78,8 +87,21 @@ public protocol ImportableObject: class {
 
 public extension ImportableObject {
     
-    static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
+    static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
         
         return true
     }
+    
+    
+    // MARK: Deprecated
+    
+    static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
+        
+        return Self.shouldInsert(from: source, in: transaction)
+    }
+    
+    func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
+        
+        try self.didInsert(from: source, in: transaction)
+    }
 }
diff --git a/Sources/Importing/ImportableUniqueObject.swift b/Sources/Importing/ImportableUniqueObject.swift
index d5f7dc4..7c54cb4 100644
--- a/Sources/Importing/ImportableUniqueObject.swift
+++ b/Sources/Importing/ImportableUniqueObject.swift
@@ -41,7 +41,7 @@ import CoreData
  CoreStore.beginAsynchronous { (transaction) -> Void in
      let json: NSDictionary = // ...
      let person = try! transaction.importUniqueObject(
-         Into(MyPersonEntity),
+         Into(),
          source: json
      )
      // ...
@@ -72,13 +72,13 @@ public protocol ImportableUniqueObject: ImportableObject {
     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.
+     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 `shouldUpdate(from:in:)` 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
+    static func shouldInsert(from source: ImportSource, in 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`.
@@ -87,24 +87,24 @@ public protocol ImportableUniqueObject: ImportableObject {
      - 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
+    static func shouldUpdate(from source: ImportSource, in 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.
+     Return the unique ID as extracted from `source`. This method is called before `shouldInsert(from:in:)` or `shouldUpdate(from:in:)`. 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?
+    static func uniqueID(from source: ImportSource, in 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(...)`.
+     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 `uniqueID(from:in:)`. 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 `update(from:in:)`.
      
      - 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
+    func didInsert(from source: ImportSource, in 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.
@@ -112,7 +112,25 @@ public protocol ImportableUniqueObject: ImportableObject {
      - 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
+    func update(from source: ImportSource, in transaction: BaseDataTransaction) throws
+    
+    
+    // MARK: Deprecated
+    
+    @available(*, deprecated: 3.0.0, renamed: "shouldInsert(from:in:)")
+    static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
+    
+    @available(*, deprecated: 3.0.0, renamed: "shouldUpdate(from:in:)")
+    static func shouldUpdateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
+    
+    @available(*, deprecated: 3.0.0, renamed: "uniqueID(from:in:)")
+    static func uniqueIDFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType?
+    
+    @available(*, deprecated: 3.0.0, renamed: "didInsert(from:in:)")
+    func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
+    
+    @available(*, deprecated: 3.0.0, renamed: "update(from:in:)")
+    func updateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
 }
 
 
@@ -120,18 +138,46 @@ public protocol ImportableUniqueObject: ImportableObject {
 
 public extension ImportableUniqueObject {
     
-    static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
+    static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
         
-        return self.shouldUpdateFromImportSource(source, inTransaction: transaction)
+        return Self.shouldUpdate(from: source, in: transaction)
     }
     
-    static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
+    static func shouldUpdate(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool{
         
         return true
     }
     
-    func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
+    func didInsert(from source: Self.ImportSource, in transaction: BaseDataTransaction) throws {
         
-        try self.updateFromImportSource(source, inTransaction: transaction)
+        try self.update(from: source, in: transaction)
+    }
+    
+    
+    // MARK: Deprecated
+    
+    static func shouldInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
+        
+        return Self.shouldInsert(from: source, in: transaction)
+    }
+    
+    static func shouldUpdateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
+        
+        return Self.shouldUpdate(from: source, in: transaction)
+    }
+    
+    static func uniqueIDFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType? {
+        
+        return try Self.uniqueID(from: source, in: transaction)
+    }
+    
+    func didInsertFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
+        
+        try self.didInsert(from: source, in: transaction)
+    }
+    
+    func updateFromImportSource(_ source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
+        
+        try self.update(from: source, in: transaction)
     }
 }
diff --git a/Sources/Info.plist b/Sources/Info.plist
index 28d15c1..e0f4bf7 100644
--- a/Sources/Info.plist
+++ b/Sources/Info.plist
@@ -15,7 +15,7 @@
 	CFBundlePackageType
 	FMWK
 	CFBundleShortVersionString
-	2.1.3
+	3.0.0
 	CFBundleSignature
 	????
 	CFBundleVersion
diff --git a/Sources/Internal/CoreStoreFetchRequest+CoreStore.swift b/Sources/Internal/CoreStoreFetchRequest+CoreStore.swift
new file mode 100644
index 0000000..b5f26fa
--- /dev/null
+++ b/Sources/Internal/CoreStoreFetchRequest+CoreStore.swift
@@ -0,0 +1,41 @@
+//
+//  CoreStoreFetchRequest+CoreStore.swift
+//  CoreStore
+//
+//  Copyright © 2016 John Rommel Estropia
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in all
+//  copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+//  SOFTWARE.
+//
+
+import Foundation
+import CoreData
+
+
+// MARK: - CoreStoreFetchRequest
+
+internal extension CoreStoreFetchRequest {
+    
+    // MARK: Internal
+    
+    @nonobjc
+    internal func dynamicCast() -> NSFetchRequest {
+        
+        return unsafeBitCast(self, to: NSFetchRequest.self)
+    }
+}
diff --git a/Sources/Internal/CoreStoreFetchedResultsController.swift b/Sources/Internal/CoreStoreFetchedResultsController.swift
index 1811aac..251ddd0 100644
--- a/Sources/Internal/CoreStoreFetchedResultsController.swift
+++ b/Sources/Internal/CoreStoreFetchedResultsController.swift
@@ -31,12 +31,12 @@ import CoreData
 
 // MARK: - CoreStoreFetchedResultsController
 
-internal final class CoreStoreFetchedResultsController: NSFetchedResultsController {
+internal final class CoreStoreFetchedResultsController: NSFetchedResultsController {
     
     // MARK: Internal
     
     @nonobjc
-    internal convenience init(dataStack: DataStack, fetchRequest: NSFetchRequest, from: From? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void) {
+    internal convenience init(dataStack: DataStack, fetchRequest: NSFetchRequest, from: From? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void) {
         
         self.init(
             context: dataStack.mainContext,
@@ -48,14 +48,14 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
     }
     
     @nonobjc
-    internal init(context: NSManagedObjectContext, fetchRequest: NSFetchRequest, from: From? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void) {
+    internal init(context: NSManagedObjectContext, fetchRequest: NSFetchRequest, from: From? = nil, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void) {
         
         _ = from?.applyToFetchRequest(
             fetchRequest,
             context: context,
             applyAffectedStores: false
         )
-        applyFetchClauses(fetchRequest: fetchRequest)
+        applyFetchClauses(fetchRequest)
         
         if let from = from {
             
@@ -68,7 +68,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
             
             guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap(From.init) else {
                 
-                CoreStore.abort("Attempted to create an \(cs_typeName(NSFetchedResultsController)) without a \(cs_typeName(From)) clause or an \(cs_typeName(NSEntityDescription)).")
+                CoreStore.abort("Attempted to create a \(CoreStoreFetchedResultsController.self) without a \(cs_typeName(From.self)) clause or an \(cs_typeName(NSEntityDescription.self)).")
             }
             
             self.reapplyAffectedStores = { fetchRequest, context in
@@ -88,16 +88,22 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
     @nonobjc
     internal func performFetchFromSpecifiedStores() throws {
         
-        if !self.reapplyAffectedStores(fetchRequest: self.fetchRequest, context: self.managedObjectContext) {
+        if !self.reapplyAffectedStores(self.fetchRequest, self.managedObjectContext) {
             
             CoreStore.log(
-                .Warning,
-                message: "Attempted to perform a fetch on an \(cs_typeName(NSFetchedResultsController)) but could not find any persistent store for the entity \(cs_typeName(self.fetchRequest.entityName))"
+                .warning,
+                message: "Attempted to perform a fetch on an \(cs_typeName(self)) but could not find any persistent store for the entity \(cs_typeName(self.fetchRequest.entityName))"
             )
         }
         try self.performFetch()
     }
     
+    @nonobjc
+    internal func dynamicCast() -> NSFetchedResultsController {
+        
+        return unsafeBitCast(self, to: NSFetchedResultsController.self)
+    }
+    
     deinit {
         
         self.delegate = nil
@@ -107,7 +113,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
     // MARK: Private
     
     @nonobjc
-    private let reapplyAffectedStores: (fetchRequest: NSFetchRequest, context: NSManagedObjectContext) -> Bool
+    private let reapplyAffectedStores: (_ fetchRequest: NSFetchRequest, _ context: NSManagedObjectContext) -> Bool
 }
 
 #endif
diff --git a/Sources/Internal/DispatchQueue+CoreStore.swift b/Sources/Internal/DispatchQueue+CoreStore.swift
new file mode 100644
index 0000000..ac3c654
--- /dev/null
+++ b/Sources/Internal/DispatchQueue+CoreStore.swift
@@ -0,0 +1,97 @@
+//
+//  DispatchQueue+CoreStore.swift
+//  CoreStore
+//
+//  Copyright © 2016 John Rommel Estropia
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in all
+//  copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+//  SOFTWARE.
+//
+
+import Foundation
+
+
+// MARK: - DispatchQueue
+
+internal extension DispatchQueue {
+    
+    @nonobjc
+    internal static func serial(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue {
+        
+        return DispatchQueue(
+            label: label,
+            qos: qos,
+            attributes: [],
+            autoreleaseFrequency: .inherit,
+            target: nil
+        )
+    }
+    
+    @nonobjc
+    internal static func concurrent(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue {
+        
+        return DispatchQueue(
+            label: label,
+            qos: qos,
+            attributes: .concurrent,
+            autoreleaseFrequency: .inherit,
+            target: nil
+        )
+    }
+    
+    @nonobjc
+    internal func cs_isCurrentExecutionContext() -> Bool {
+        
+        let specific = ObjectIdentifier(self)
+        
+        self.setSpecific(key: Static.specificKey, value: specific)
+        return DispatchQueue.getSpecific(key: Static.specificKey) == specific
+    }
+    
+    @nonobjc
+    internal func cs_sync(_ closure: () throws -> T) rethrows -> T {
+        
+        return try self.sync { try autoreleasepool(invoking: closure) }
+    }
+    
+    @nonobjc
+    internal func cs_async(_ closure: @escaping () -> Void) {
+        
+        self.async { autoreleasepool(invoking: closure) }
+    }
+    
+    @nonobjc
+    internal func cs_barrierSync(_ closure: () throws -> T) rethrows -> T {
+        
+        return try self.sync(flags: .barrier) { try autoreleasepool(invoking: closure) }
+    }
+    
+    @nonobjc
+    internal func cs_barrierAsync(_ closure: @escaping () -> Void) {
+        
+        self.async(flags: .barrier) { autoreleasepool(invoking: closure) }
+    }
+    
+    
+    // MARK: Private
+    
+    private enum Static {
+        
+        static let specificKey = DispatchSpecificKey()
+    }
+}
diff --git a/Sources/Internal/FetchedResultsControllerDelegate.swift b/Sources/Internal/FetchedResultsControllerDelegate.swift
index fbbe544..3d8a8a5 100644
--- a/Sources/Internal/FetchedResultsControllerDelegate.swift
+++ b/Sources/Internal/FetchedResultsControllerDelegate.swift
@@ -33,21 +33,21 @@ import CoreData
 
 internal protocol FetchedResultsControllerHandler: class {
     
-    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)
+    func controller(_ controller: NSFetchedResultsController, didChangeObject anObject: Any, atIndexPath indexPath: IndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
     
-    func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
+    func controller(_ controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
     
-    func controllerWillChangeContent(controller: NSFetchedResultsController)
+    func controllerWillChangeContent(_ controller: NSFetchedResultsController)
     
-    func controllerDidChangeContent(controller: NSFetchedResultsController)
+    func controllerDidChangeContent(_ controller: NSFetchedResultsController)
     
-    func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String?
+    func controller(_ controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String?
 }
 
 
 // MARK: - FetchedResultsControllerDelegate
 
-internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate {
+internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate {
     
     // MARK: Internal
     
@@ -58,7 +58,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
     internal weak var handler: FetchedResultsControllerHandler?
     
     @nonobjc
-    internal weak var fetchedResultsController: NSFetchedResultsController? {
+    internal weak var fetchedResultsController: CoreStoreFetchedResultsController? {
         
         didSet {
             
@@ -76,7 +76,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
     // MARK: NSFetchedResultsControllerDelegate
     
     @objc
-    dynamic func controllerWillChangeContent(controller: NSFetchedResultsController) {
+    dynamic func controllerWillChangeContent(_ controller: NSFetchedResultsController) {
         
         guard self.enabled else {
             
@@ -90,7 +90,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
     }
     
     @objc
-    dynamic func controllerDidChangeContent(controller: NSFetchedResultsController) {
+    dynamic func controllerDidChangeContent(_ controller: NSFetchedResultsController) {
         
         guard self.enabled else {
             
@@ -101,7 +101,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
     }
     
     @objc
-    dynamic func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
+    dynamic func controller(_ controller: NSFetchedResultsController, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
         
         guard self.enabled else {
             
@@ -120,21 +120,32 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
         // 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
+
+        if #available(iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
+         
+            // I don't know if iOS 10 even attempted to fix this mess...
+            if case .update = actualType,
+                indexPath != nil,
+                newIndexPath != nil {
+                
+                actualType = .move
+            }
+        }
         
         if #available(iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
             
             // I don't know if iOS 10 even attempted to fix this mess...
-            if case .Update = actualType
-                where indexPath != nil && newIndexPath != nil {
+            if case .update = actualType,
+                indexPath != nil && newIndexPath != nil {
                 
-                actualType = .Move
+                actualType = .move
             }
         }
         
         switch actualType {
             
-        case .Update:
-            guard let section = indexPath?.indexAtPosition(0) else {
+        case .update:
+            guard let section = indexPath?[0] else {
                 
                 return
             }
@@ -144,7 +155,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
                 return
             }
             
-        case .Move:
+        case .move:
             guard let indexPath = indexPath, let newIndexPath = newIndexPath else {
                 
                 return
@@ -153,25 +164,25 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
                 
                 break
             }
-            if self.insertedSections.contains(indexPath.indexAtPosition(0)) {
+            if self.insertedSections.contains(indexPath[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,
+                    forChangeType: .move,
                     newIndexPath: newIndexPath
                 )
                 return
             }
-            if self.deletedSections.contains(indexPath.indexAtPosition(0)) {
+            if self.deletedSections.contains(indexPath[0]) {
                 
                 self.handler?.controller(
                     controller,
                     didChangeObject: anObject,
                     atIndexPath: nil,
-                    forChangeType: .Insert,
+                    forChangeType: .insert,
                     newIndexPath: indexPath
                 )
                 return
@@ -180,7 +191,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
                 controller,
                 didChangeObject: anObject,
                 atIndexPath: indexPath,
-                forChangeType: .Update,
+                forChangeType: .update,
                 newIndexPath: nil
             )
             return
@@ -199,7 +210,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
     }
     
     @objc
-    dynamic func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
+    dynamic func controller(_ controller: NSFetchedResultsController, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
         
         guard self.enabled else {
             
@@ -208,8 +219,8 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
         
         switch type {
             
-        case .Delete:   self.deletedSections.insert(sectionIndex)
-        case .Insert:   self.insertedSections.insert(sectionIndex)
+        case .delete:   self.deletedSections.insert(sectionIndex)
+        case .insert:   self.insertedSections.insert(sectionIndex)
         default: break
         }
         
@@ -222,7 +233,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
     }
     
     @objc
-    dynamic func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String) -> String? {
+    dynamic func controller(_ controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String) -> String? {
         
         return self.handler?.controller(
             controller,
diff --git a/Sources/Internal/Functions.swift b/Sources/Internal/Functions.swift
index ce944de..aa75930 100644
--- a/Sources/Internal/Functions.swift
+++ b/Sources/Internal/Functions.swift
@@ -25,70 +25,9 @@
 
 import Foundation
 
+// MARK: Associated Objects
 
-// MARK: - Custom AutoreleasePool
-
-internal func cs_autoreleasepool(@noescape closure: () -> Void) {
-    
-    autoreleasepool(closure)
-}
-
-internal func cs_autoreleasepool(@noescape closure: () -> T) -> T {
-    
-    var closureValue: T!
-    autoreleasepool {
-        
-        closureValue = closure()
-    }
-    
-    return closureValue
-}
-
-internal func cs_autoreleasepool(@noescape closure: () throws -> T) throws -> T {
-    
-    var closureValue: T!
-    var closureError: ErrorType?
-    autoreleasepool {
-        
-        do {
-            
-            closureValue = try closure()
-        }
-        catch {
-            
-            closureError = error
-        }
-    }
-    
-    if let closureError = closureError {
-        
-        throw closureError
-    }
-    return closureValue
-}
-
-internal func cs_autoreleasepool(@noescape closure: () throws -> Void) throws {
-    
-    var closureError: ErrorType?
-    autoreleasepool {
-        
-        do {
-            
-            try closure()
-        }
-        catch {
-            
-            closureError = error
-        }
-    }
-    
-    if let closureError = closureError {
-        
-        throw closureError
-    }
-}
-
-internal func cs_getAssociatedObjectForKey(key: UnsafePointer, inObject object: AnyObject) -> T? {
+internal func cs_getAssociatedObjectForKey(_ key: UnsafeRawPointer, inObject object: Any) -> T? {
     
     switch objc_getAssociatedObject(object, key) {
         
@@ -103,17 +42,17 @@ internal func cs_getAssociatedObjectForKey(key: UnsafePointer(associatedObject: T?, forKey key: UnsafePointer, inObject object: AnyObject) {
+internal func cs_setAssociatedRetainedObject(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) {
     
     objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
 }
 
-internal func cs_setAssociatedCopiedObject(associatedObject: T?, forKey key: UnsafePointer, inObject object: AnyObject) {
+internal func cs_setAssociatedCopiedObject(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) {
     
     objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_COPY_NONATOMIC)
 }
 
-internal func cs_setAssociatedWeakObject(associatedObject: T?, forKey key: UnsafePointer, inObject object: AnyObject) {
+internal func cs_setAssociatedWeakObject(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) {
     
     if let associatedObject = associatedObject {
         
@@ -128,22 +67,27 @@ internal func cs_setAssociatedWeakObject(associatedObject: T?, for
 
 // MARK: Printing Utilities
 
-internal func cs_typeName(value: T) -> String {
+internal func cs_typeName(_ value: T) -> String {
     
-    return "'\(String(reflecting: value.dynamicType))'"
+    return "'\(String(reflecting: type(of: value)))'"
 }
 
-internal func cs_typeName(value: T.Type) -> String {
+internal func cs_typeName(_ value: T.Type) -> String {
     
     return "'\(value)'"
 }
 
-internal func cs_typeName(value: AnyClass) -> String {
+internal func cs_typeName(_ value: AnyClass) -> String {
     
     return "'\(value)'"
 }
 
-internal func cs_typeName(name: String?) -> String {
+internal func cs_typeName(_ name: String) -> String {
+    
+    return "<\(name)>"
+}
+
+internal func cs_typeName(_ name: String?) -> String {
     
     return "<\(name ?? "unknown")>"
 }
diff --git a/Sources/Internal/MigrationManager.swift b/Sources/Internal/MigrationManager.swift
index 3ed0a42..eda35c8 100644
--- a/Sources/Internal/MigrationManager.swift
+++ b/Sources/Internal/MigrationManager.swift
@@ -29,15 +29,15 @@ import CoreData
 
 // MARK: - MigrationManager
 
-internal final class MigrationManager: NSMigrationManager, NSProgressReporting {
+internal final class MigrationManager: NSMigrationManager, ProgressReporting {
     
     // MARK: NSObject
     
-    override func didChangeValueForKey(key: String) {
+    override func didChangeValue(forKey key: String) {
         
-        super.didChangeValueForKey(key)
+        super.didChangeValue(forKey: key)
         
-        guard key == "migrationProgress" else {
+        guard key == #keyPath(NSMigrationManager.migrationProgress) else {
             
             return
         }
@@ -48,7 +48,7 @@ internal final class MigrationManager: NSMigrationManager, NSProgressReporting {
     
     // MARK: NSMigrationManager
 
-    init(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, progress: NSProgress) {
+    init(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, progress: Progress) {
         
         self.progress = progress
         
@@ -56,7 +56,7 @@ internal final class MigrationManager: NSMigrationManager, NSProgressReporting {
     }
     
 
-    // MARK: NSProgressReporting
+    // MARK: ProgressReporting
     
-    let progress: NSProgress
+    let progress: Progress
 }
diff --git a/Sources/Internal/NSManagedObjectContext+CoreStore.swift b/Sources/Internal/NSManagedObjectContext+CoreStore.swift
index 8840947..d461551 100644
--- a/Sources/Internal/NSManagedObjectContext+CoreStore.swift
+++ b/Sources/Internal/NSManagedObjectContext+CoreStore.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - NSManagedObjectContext
@@ -50,7 +47,7 @@ internal extension NSManagedObjectContext {
         set {
             
             cs_setAssociatedCopiedObject(
-                NSNumber(bool: newValue),
+                NSNumber(value: newValue),
                 forKey: &PropertyKeys.shouldCascadeSavesToParent,
                 inObject: self
             )
@@ -58,40 +55,30 @@ internal extension NSManagedObjectContext {
     }
     
     @nonobjc
-    internal func entityDescriptionForEntityType(entity: NSManagedObject.Type) -> NSEntityDescription? {
+    internal func entityDescriptionForEntityType(_ entity: NSManagedObject.Type) -> NSEntityDescription? {
         
         return self.entityDescriptionForEntityClass(entity)
     }
     
     @nonobjc
-    internal func entityDescriptionForEntityClass(entity: AnyClass) -> NSEntityDescription? {
+    internal func entityDescriptionForEntityClass(_ entity: AnyClass) -> NSEntityDescription? {
         
         guard let entityName = self.parentStack?.entityNameForEntityClass(entity) else {
             
             return nil
         }
-        return NSEntityDescription.entityForName(
-            entityName,
-            inManagedObjectContext: self
+        return NSEntityDescription.entity(
+            forEntityName: entityName,
+            in: self
         )
     }
     
     @nonobjc
-    internal func setupForCoreStoreWithContextName(contextName: String) {
-
-        #if USE_FRAMEWORKS
-            
-            self.name = contextName
-        #else
-            
-            if #available(iOS 8.0, *) {
-                
-                self.name = contextName
-            }
-        #endif
+    internal func setupForCoreStoreWithContextName(_ contextName: String) {
         
+        self.name = contextName
         self.observerForWillSaveNotification = NotificationObserver(
-            notificationName: NSManagedObjectContextWillSaveNotification,
+            notificationName: NSNotification.Name.NSManagedObjectContextWillSave,
             object: self,
             closure: { (note) -> Void in
                 
@@ -105,7 +92,7 @@ internal extension NSManagedObjectContext {
                 
                 do {
                     
-                    try context.obtainPermanentIDsForObjects(Array(insertedObjects))
+                    try context.obtainPermanentIDs(for: Array(insertedObjects))
                 }
                 catch {
                     
diff --git a/Sources/Internal/NSManagedObjectContext+Querying.swift b/Sources/Internal/NSManagedObjectContext+Querying.swift
index 81dd9d3..bb44498 100644
--- a/Sources/Internal/NSManagedObjectContext+Querying.swift
+++ b/Sources/Internal/NSManagedObjectContext+Querying.swift
@@ -29,20 +29,20 @@ import CoreData
 
 // MARK: - NSManagedObjectContext
 
-internal extension NSManagedObjectContext {
+extension NSManagedObjectContext: FetchableSource, QueryableSource {
     
-    // MARK: Internal: Fetch Existing
+    // MARK: FetchableSource
     
     @nonobjc
-    internal func fetchExisting(object: T) -> T? {
+    public func fetchExisting(_ object: T) -> T? {
         
-        if object.objectID.temporaryID {
+        if object.objectID.isTemporaryID {
             
             do {
                 
                 try withExtendedLifetime(self) { (context: NSManagedObjectContext) -> Void in
                     
-                    try context.obtainPermanentIDsForObjects([object])
+                    try context.obtainPermanentIDs(for: [object])
                 }
             }
             catch {
@@ -54,10 +54,9 @@ internal extension NSManagedObjectContext {
                 return nil
             }
         }
-        
         do {
             
-            let existingObject = try self.existingObjectWithID(object.objectID)
+            let existingObject = try self.existingObject(with: object.objectID)
             return (existingObject as! T)
         }
         catch {
@@ -70,125 +69,86 @@ internal extension NSManagedObjectContext {
         }
     }
     
-    
-    // MARK: Internal: Fetch One
+    @nonobjc
+    public func fetchExisting(_ objectID: NSManagedObjectID) -> T? {
+        
+        do {
+            
+            return (try self.existingObject(with: objectID) as! T)
+        }
+        catch _ {
+            
+            return nil
+        }
+    }
     
     @nonobjc
-    internal func fetchOne(from: From, _ fetchClauses: FetchClause...) -> T? {
+    public func fetchExisting(_ objects: S) -> [T] where S.Iterator.Element == T {
+        
+        return objects.flatMap { (try? self.existingObject(with: $0.objectID)) as? T }
+    }
+    
+    @nonobjc
+    public func fetchExisting(_ objectIDs: S) -> [T] where S.Iterator.Element == NSManagedObjectID {
+        
+        return objectIDs.flatMap { (try? self.existingObject(with: $0)) as? T }
+    }
+    
+    @nonobjc
+    public func fetchOne(_ from: From, _ fetchClauses: FetchClause...) -> T? {
+        
         
         return self.fetchOne(from, fetchClauses)
     }
     
     @nonobjc
-    internal func fetchOne(from: From, _ fetchClauses: [FetchClause]) -> T? {
+    public func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> T? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
         
         fetchRequest.fetchLimit = 1
-        fetchRequest.resultType = .ManagedObjectResultType
+        fetchRequest.resultType = .managedObjectResultType
         fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
         
         guard storeFound else {
             
             return nil
         }
-        return self.fetchOne(fetchRequest)
+        return self.fetchOne(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func fetchOne(fetchRequest: NSFetchRequest) -> T? {
-        
-        var fetchResults: [T]?
-        var fetchError: ErrorType?
-        self.performBlockAndWait {
-            
-            do {
-                
-                fetchResults = try self.executeFetchRequest(fetchRequest) as? [T]
-            }
-            catch {
-                
-                fetchError = error
-            }
-        }
-        if fetchResults == nil {
-            
-            CoreStore.log(
-                CoreStoreError(fetchError),
-                "Failed executing fetch request."
-            )
-            return nil
-        }
-        
-        return fetchResults?.first
-    }
-    
-    
-    // MARK: Internal: Fetch All
-    
-    @nonobjc
-    internal func fetchAll(from: From, _ fetchClauses: FetchClause...) -> [T]? {
+    public func fetchAll(_ from: From, _ fetchClauses: FetchClause...) -> [T]? {
         
         return self.fetchAll(from, fetchClauses)
     }
     
     @nonobjc
-    internal func fetchAll(from: From, _ fetchClauses: [FetchClause]) -> [T]? {
+    public func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [T]? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
         
         fetchRequest.fetchLimit = 0
-        fetchRequest.resultType = .ManagedObjectResultType
+        fetchRequest.resultType = .managedObjectResultType
         fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
         
         guard storeFound else {
             
             return nil
         }
-        return self.fetchAll(fetchRequest)
+        return self.fetchAll(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func fetchAll(fetchRequest: NSFetchRequest) -> [T]? {
-        
-        var fetchResults: [T]?
-        var fetchError: ErrorType?
-        self.performBlockAndWait {
-            
-            do {
-                
-                fetchResults = try self.executeFetchRequest(fetchRequest) as? [T]
-            }
-            catch {
-                
-                fetchError = error
-            }
-        }
-        if fetchResults == nil {
-            
-            CoreStore.log(
-                CoreStoreError(fetchError),
-                "Failed executing fetch request."
-            )
-            return nil
-        }
-        
-        return fetchResults
-    }
-    
-    
-    // MARK: Internal: Count
-    
-    @nonobjc
-    internal func fetchCount(from: From, _ fetchClauses: FetchClause...) -> Int? {
+    public func fetchCount(_ from: From, _ fetchClauses: FetchClause...) -> Int? {
     
         return self.fetchCount(from, fetchClauses)
     }
     
     @nonobjc
-    internal func fetchCount(from: From, _ fetchClauses: [FetchClause]) -> Int? {
+    public func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
@@ -198,127 +158,65 @@ internal extension NSManagedObjectContext {
             
             return nil
         }
-        return self.fetchCount(fetchRequest)
+        return self.fetchCount(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func fetchCount(fetchRequest: NSFetchRequest) -> Int? {
-        
-        var count = 0
-        var countError: ErrorType?
-        self.performBlockAndWait {
-            
-            do {
-                
-                count = try self.countForFetchRequest(fetchRequest)
-            }
-            catch {
-                
-                countError = error
-            }
-        }
-        if count == NSNotFound {
-            
-            CoreStore.log(
-                CoreStoreError(countError),
-                "Failed executing fetch request."
-            )
-            return nil
-        }
-        
-        return count
-    }
-    
-    
-    // MARK: Internal: Object ID
-    
-    @nonobjc
-    internal func fetchObjectID(from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
+    public func fetchObjectID(_ from: From, _ fetchClauses: FetchClause...) -> NSManagedObjectID? {
         
         return self.fetchObjectID(from, fetchClauses)
     }
     
     @nonobjc
-    internal func fetchObjectID(from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
+    public func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
         
         fetchRequest.fetchLimit = 1
-        fetchRequest.resultType = .ManagedObjectIDResultType
+        fetchRequest.resultType = .managedObjectIDResultType
         fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
         
         guard storeFound else {
             
             return nil
         }
-        return self.fetchObjectID(fetchRequest)
+        return self.fetchObjectID(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func fetchObjectID(fetchRequest: NSFetchRequest) -> NSManagedObjectID? {
-        
-        var fetchResults: [NSManagedObjectID]?
-        var fetchError: ErrorType?
-        self.performBlockAndWait {
-            
-            do {
-                
-                fetchResults = try self.executeFetchRequest(fetchRequest) as? [NSManagedObjectID]
-            }
-            catch {
-                
-                fetchError = error
-            }
-        }
-        if fetchResults == nil {
-            
-            CoreStore.log(
-                CoreStoreError(fetchError),
-                "Failed executing fetch request."
-            )
-            return nil
-        }
-        
-        return fetchResults?.first
-    }
-    
-    
-    // MARK: Internal: Object IDs
-    
-    @nonobjc
-    internal func fetchObjectIDs(from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
+    public func fetchObjectIDs(_ from: From, _ fetchClauses: FetchClause...) -> [NSManagedObjectID]? {
         
         return self.fetchObjectIDs(from, fetchClauses)
     }
     
     @nonobjc
-    internal func fetchObjectIDs(from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
+    public func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
         
         fetchRequest.fetchLimit = 0
-        fetchRequest.resultType = .ManagedObjectIDResultType
+        fetchRequest.resultType = .managedObjectIDResultType
         fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
         
         guard storeFound else {
             
             return nil
         }
-        return self.fetchObjectIDs(fetchRequest)
+        return self.fetchObjectIDs(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func fetchObjectIDs(fetchRequest: NSFetchRequest) -> [NSManagedObjectID]? {
+    internal func fetchObjectIDs(_ fetchRequest: NSFetchRequest) -> [NSManagedObjectID]? {
         
         var fetchResults: [NSManagedObjectID]?
-        var fetchError: ErrorType?
-        self.performBlockAndWait {
+        var fetchError: Error?
+        self.performAndWait {
             
             do {
                 
-                fetchResults = try self.executeFetchRequest(fetchRequest) as? [NSManagedObjectID]
+                fetchResults = try self.fetch(fetchRequest)
             }
             catch {
                 
@@ -333,85 +231,20 @@ internal extension NSManagedObjectContext {
             )
             return nil
         }
-        
         return fetchResults
     }
     
     
-    // MARK: Internal: Delete All
+    // MARK: QueryableSource
     
     @nonobjc
-    internal func deleteAll(from: From, _ deleteClauses: DeleteClause...) -> Int? {
-        
-        return self.deleteAll(from, deleteClauses)
-    }
-    
-    @nonobjc
-    internal func deleteAll(from: From, _ deleteClauses: [DeleteClause]) -> Int? {
-        
-        let fetchRequest = CoreStoreFetchRequest()
-        let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
-        
-        fetchRequest.fetchLimit = 0
-        fetchRequest.resultType = .ManagedObjectResultType
-        fetchRequest.returnsObjectsAsFaults = true
-        fetchRequest.includesPropertyValues = false
-        deleteClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
-        
-        guard storeFound else {
-            
-            return nil
-        }
-        return self.deleteAll(fetchRequest)
-    }
-    
-    @nonobjc
-    internal func deleteAll(fetchRequest: NSFetchRequest) -> Int? {
-        
-        var numberOfDeletedObjects: Int?
-        var fetchError: ErrorType?
-        self.performBlockAndWait {
-            
-            cs_autoreleasepool {
-                
-                do {
-                    
-                    let fetchResults = try self.executeFetchRequest(fetchRequest) as? [NSManagedObject] ?? []
-                    for object in fetchResults {
-                        
-                        self.deleteObject(object)
-                    }
-                    numberOfDeletedObjects = fetchResults.count
-                }
-                catch {
-                    
-                    fetchError = error
-                }
-            }
-        }
-        if numberOfDeletedObjects == nil {
-            
-            CoreStore.log(
-                CoreStoreError(fetchError),
-                "Failed executing fetch request."
-            )
-            return nil
-        }
-        
-        return numberOfDeletedObjects
-    }
-    
-    
-    // MARK: Internal: Value
-    
-    @nonobjc
-    internal func queryValue(from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? {
+    public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? {
         
         return self.queryValue(from, selectClause, queryClauses)
     }
     
     @nonobjc
-    internal func queryValue(from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? {
+    public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
@@ -430,82 +263,13 @@ internal extension NSManagedObjectContext {
     }
     
     @nonobjc
-    internal func queryValue(selectTerms: [SelectTerm], fetchRequest: NSFetchRequest) -> U? {
-        
-        var fetchResults: [AnyObject]?
-        var fetchError: ErrorType?
-        self.performBlockAndWait {
-            
-            do {
-                
-                fetchResults = try self.executeFetchRequest(fetchRequest)
-            }
-            catch {
-                
-                fetchError = error
-            }
-        }
-        if let fetchResults = fetchResults {
-            
-            if let rawResult = fetchResults.first as? NSDictionary,
-                let rawObject: AnyObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] {
-                
-                return Select.ReturnType.fromResultObject(rawObject)
-            }
-            return nil
-        }
-        
-        CoreStore.log(
-            CoreStoreError(fetchError),
-            "Failed executing fetch request."
-        )
-        return nil
-    }
-    
-    @nonobjc
-    internal func queryValue(selectTerms: [SelectTerm], fetchRequest: NSFetchRequest) -> AnyObject? {
-        
-        var fetchResults: [AnyObject]?
-        var fetchError: ErrorType?
-        self.performBlockAndWait {
-            
-            do {
-                
-                fetchResults = try self.executeFetchRequest(fetchRequest)
-            }
-            catch {
-                
-                fetchError = error
-            }
-        }
-        if let fetchResults = fetchResults {
-            
-            if let rawResult = fetchResults.first as? NSDictionary,
-                let rawObject: AnyObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] {
-                
-                return rawObject
-            }
-            return nil
-        }
-        
-        CoreStore.log(
-            CoreStoreError(fetchError),
-            "Failed executing fetch request."
-        )
-        return nil
-    }
-    
-    
-    // MARK: Internal: Attributes
-    
-    @nonobjc
-    internal func queryAttributes(from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[NSString: AnyObject]]? {
+    public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? {
         
         return self.queryAttributes(from, selectClause, queryClauses)
     }
     
     @nonobjc
-    internal func queryAttributes(from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[NSString: AnyObject]]? {
+    public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
@@ -522,16 +286,210 @@ internal extension NSManagedObjectContext {
         return self.queryAttributes(fetchRequest)
     }
     
+    
+    // MARK: FetchableSource, QueryableSource
+    
     @nonobjc
-    internal func queryAttributes(fetchRequest: NSFetchRequest) -> [[NSString: AnyObject]]? {
+    public func internalContext() -> NSManagedObjectContext {
         
-        var fetchResults: [AnyObject]?
-        var fetchError: ErrorType?
-        self.performBlockAndWait {
+        return self
+    }
+}
+
+
+// MARK: - NSManagedObjectContext (Internal)
+
+internal extension NSManagedObjectContext {
+    
+    // MARK: Fetching
+    
+    @nonobjc
+    internal func fetchOne(_ fetchRequest: NSFetchRequest) -> T? {
+        
+        var fetchResults: [T]?
+        var fetchError: Error?
+        self.performAndWait {
             
             do {
                 
-                fetchResults = try self.executeFetchRequest(fetchRequest)
+                fetchResults = try self.fetch(fetchRequest)
+            }
+            catch {
+                
+                fetchError = error
+            }
+        }
+        if fetchResults == nil {
+            
+            CoreStore.log(
+                CoreStoreError(fetchError),
+                "Failed executing fetch request."
+            )
+            return nil
+        }
+        return fetchResults?.first
+    }
+    
+    @nonobjc
+    internal func fetchAll(_ fetchRequest: NSFetchRequest) -> [T]? {
+        
+        var fetchResults: [T]?
+        var fetchError: Error?
+        self.performAndWait {
+            
+            do {
+                
+                fetchResults = try self.fetch(fetchRequest)
+            }
+            catch {
+                
+                fetchError = error
+            }
+        }
+        if fetchResults == nil {
+            
+            CoreStore.log(
+                CoreStoreError(fetchError),
+                "Failed executing fetch request."
+            )
+            return nil
+        }
+        return fetchResults
+    }
+    
+    @nonobjc
+    internal func fetchCount(_ fetchRequest: NSFetchRequest) -> Int? {
+        
+        var count = 0
+        var countError: Error?
+        self.performAndWait {
+            
+            do {
+                
+                count = try self.count(for: fetchRequest)
+            }
+            catch {
+                
+                countError = error
+            }
+        }
+        if count == NSNotFound {
+            
+            CoreStore.log(
+                CoreStoreError(countError),
+                "Failed executing count request."
+            )
+            return nil
+        }
+        return count
+    }
+    
+    @nonobjc
+    internal func fetchObjectID(_ fetchRequest: NSFetchRequest) -> NSManagedObjectID? {
+        
+        var fetchResults: [NSManagedObjectID]?
+        var fetchError: Error?
+        self.performAndWait {
+            
+            do {
+                
+                fetchResults = try self.fetch(fetchRequest)
+            }
+            catch {
+                
+                fetchError = error
+            }
+        }
+        if fetchResults == nil {
+            
+            CoreStore.log(
+                CoreStoreError(fetchError),
+                "Failed executing fetch request."
+            )
+            return nil
+        }
+        return fetchResults?.first
+    }
+    
+    
+    // MARK: Querying
+    
+    @nonobjc
+    internal func queryValue(_ selectTerms: [SelectTerm], fetchRequest: NSFetchRequest) -> U? {
+        
+        var fetchResults: [Any]?
+        var fetchError: Error?
+        self.performAndWait {
+            
+            do {
+                
+                fetchResults = try self.fetch(fetchRequest)
+            }
+            catch {
+                
+                fetchError = error
+            }
+        }
+        if let fetchResults = fetchResults {
+            
+            if let rawResult = fetchResults.first as? NSDictionary,
+                let rawObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] {
+                
+                return Select.ReturnType.fromResultObject(rawObject)
+            }
+            return nil
+        }
+        
+        CoreStore.log(
+            CoreStoreError(fetchError),
+            "Failed executing fetch request."
+        )
+        return nil
+    }
+    
+    @nonobjc
+    internal func queryValue(_ selectTerms: [SelectTerm], fetchRequest: NSFetchRequest) -> Any? {
+        
+        var fetchResults: [Any]?
+        var fetchError: Error?
+        self.performAndWait {
+            
+            do {
+                
+                fetchResults = try self.fetch(fetchRequest)
+            }
+            catch {
+                
+                fetchError = error
+            }
+        }
+        if let fetchResults = fetchResults {
+            
+            if let rawResult = fetchResults.first as? NSDictionary,
+                let rawObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] {
+                
+                return rawObject
+            }
+            return nil
+        }
+        
+        CoreStore.log(
+            CoreStoreError(fetchError),
+            "Failed executing fetch request."
+        )
+        return nil
+    }
+    
+    @nonobjc
+    internal func queryAttributes(_ fetchRequest: NSFetchRequest) -> [[String: Any]]? {
+        
+        var fetchResults: [Any]?
+        var fetchError: Error?
+        self.performAndWait {
+            
+            do {
+                
+                fetchResults = try self.fetch(fetchRequest)
             }
             catch {
                 
@@ -549,4 +507,67 @@ internal extension NSManagedObjectContext {
         )
         return nil
     }
+    
+    
+    // MARK: Deleting
+    
+    @nonobjc
+    internal func deleteAll(_ from: From, _ deleteClauses: DeleteClause...) -> Int? {
+        
+        return self.deleteAll(from, deleteClauses)
+    }
+    
+    @nonobjc
+    internal func deleteAll(_ from: From, _ deleteClauses: [DeleteClause]) -> Int? {
+        
+        let fetchRequest = CoreStoreFetchRequest()
+        let storeFound = from.applyToFetchRequest(fetchRequest, context: self)
+        
+        fetchRequest.fetchLimit = 0
+        fetchRequest.resultType = .managedObjectResultType
+        fetchRequest.returnsObjectsAsFaults = true
+        fetchRequest.includesPropertyValues = false
+        deleteClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
+        
+        guard storeFound else {
+            
+            return nil
+        }
+        return self.deleteAll(fetchRequest.dynamicCast())
+    }
+    
+    @nonobjc
+    internal func deleteAll(_ fetchRequest: NSFetchRequest) -> Int? {
+        
+        var numberOfDeletedObjects: Int?
+        var fetchError: Error?
+        self.performAndWait {
+            
+            autoreleasepool {
+                
+                do {
+                    
+                    let fetchResults = try self.fetch(fetchRequest)
+                    for object in fetchResults {
+                        
+                        self.delete(object)
+                    }
+                    numberOfDeletedObjects = fetchResults.count
+                }
+                catch {
+                    
+                    fetchError = error
+                }
+            }
+        }
+        if numberOfDeletedObjects == nil {
+            
+            CoreStore.log(
+                CoreStoreError(fetchError),
+                "Failed executing fetch request."
+            )
+            return nil
+        }
+        return numberOfDeletedObjects
+    }
 }
diff --git a/Sources/Internal/NSManagedObjectContext+Setup.swift b/Sources/Internal/NSManagedObjectContext+Setup.swift
index 77fb99c..d178976 100644
--- a/Sources/Internal/NSManagedObjectContext+Setup.swift
+++ b/Sources/Internal/NSManagedObjectContext+Setup.swift
@@ -38,7 +38,7 @@ internal extension NSManagedObjectContext {
         
         get {
             
-            if let parentContext = self.parentContext {
+            if let parentContext = self.parent {
                 
                 return parentContext.parentStack
             }
@@ -47,7 +47,7 @@ internal extension NSManagedObjectContext {
         }
         set {
             
-            guard self.parentContext == nil else {
+            guard self.parent == nil else {
                 
                 return
             }
@@ -61,9 +61,9 @@ internal extension NSManagedObjectContext {
     }
     
     @nonobjc
-    internal static func rootSavingContextForCoordinator(coordinator: NSPersistentStoreCoordinator) -> NSManagedObjectContext {
+    internal static func rootSavingContextForCoordinator(_ coordinator: NSPersistentStoreCoordinator) -> NSManagedObjectContext {
         
-        let context = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
+        let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
         context.persistentStoreCoordinator = coordinator
         context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
         context.undoManager = nil
@@ -72,18 +72,20 @@ internal extension NSManagedObjectContext {
         #if os(iOS) || os(OSX)
             
         context.observerForDidImportUbiquitousContentChangesNotification = NotificationObserver(
-            notificationName: NSPersistentStoreDidImportUbiquitousContentChangesNotification,
+            notificationName: NSNotification.Name.NSPersistentStoreDidImportUbiquitousContentChanges,
             object: coordinator,
             closure: { [weak context] (note) -> Void in
                 
-                context?.performBlock { () -> Void in
+                context?.perform { () -> Void in
                     
-                    let updatedObjectIDs = (note.userInfo?[NSUpdatedObjectsKey] as? Set) ?? []
-                    for objectID in updatedObjectIDs {
+                    if let updatedObjectIDs = (note.userInfo?[NSUpdatedObjectsKey] as? Set) {
                         
-                        context?.objectWithID(objectID).willAccessValueForKey(nil)
+                        for objectID in updatedObjectIDs {
+                            
+                            context?.object(with: objectID).willAccessValue(forKey: nil)
+                        }
                     }
-                    context?.mergeChangesFromContextDidSaveNotification(note)
+                    context?.mergeChanges(fromContextDidSave: note)
                 }
             }
         )
@@ -94,15 +96,15 @@ internal extension NSManagedObjectContext {
     }
     
     @nonobjc
-    internal static func mainContextForRootContext(rootContext: NSManagedObjectContext) -> NSManagedObjectContext {
+    internal static func mainContextForRootContext(_ rootContext: NSManagedObjectContext) -> NSManagedObjectContext {
         
-        let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
-        context.parentContext = rootContext
+        let context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
+        context.parent = rootContext
         context.mergePolicy = NSRollbackMergePolicy
         context.undoManager = nil
         context.setupForCoreStoreWithContextName("com.corestore.maincontext")
         context.observerForDidSaveNotification = NotificationObserver(
-            notificationName: NSManagedObjectContextDidSaveNotification,
+            notificationName: NSNotification.Name.NSManagedObjectContextDidSave,
             object: rootContext,
             closure: { [weak context] (note) -> Void in
                 
@@ -113,21 +115,22 @@ internal extension NSManagedObjectContext {
                 }
                 let mergeChanges = { () -> Void in
                     
-                    let updatedObjects = (note.userInfo?[NSUpdatedObjectsKey] as? Set) ?? []
-                    for object in updatedObjects {
+                    if let updatedObjects = (note.userInfo?[NSUpdatedObjectsKey] as? Set) {
                         
-                        context.objectWithID(object.objectID).willAccessValueForKey(nil)
+                        for object in updatedObjects {
+                            
+                            context.object(with: object.objectID).willAccessValue(forKey: nil)
+                        }
                     }
-                    context.mergeChangesFromContextDidSaveNotification(note)
+                    context.mergeChanges(fromContextDidSave: note)
                 }
-                
                 if rootContext.isSavingSynchronously == true {
                     
-                    context.performBlockAndWait(mergeChanges)
+                    context.performAndWait(mergeChanges)
                 }
                 else {
                     
-                    context.performBlock(mergeChanges)
+                    context.perform(mergeChanges)
                 }
             }
         )
diff --git a/Sources/Internal/NSManagedObjectContext+Transaction.swift b/Sources/Internal/NSManagedObjectContext+Transaction.swift
index 3d17ea1..5561425 100644
--- a/Sources/Internal/NSManagedObjectContext+Transaction.swift
+++ b/Sources/Internal/NSManagedObjectContext+Transaction.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - NSManagedObjectContext
@@ -70,13 +67,55 @@ internal extension NSManagedObjectContext {
         set {
             
             cs_setAssociatedWeakObject(
-                newValue.flatMap { NSNumber(bool: $0) },
+                newValue.flatMap { NSNumber(value: $0) },
                 forKey: &PropertyKeys.isSavingSynchronously,
                 inObject: self
             )
         }
     }
     
+    @nonobjc
+    internal var isTransactionContext: Bool {
+        
+        get {
+            
+            let value: NSNumber? = cs_getAssociatedObjectForKey(
+                &PropertyKeys.isTransactionContext,
+                inObject: self
+            )
+            return value?.boolValue == true
+        }
+        set {
+            
+            cs_setAssociatedCopiedObject(
+                NSNumber(value: newValue),
+                forKey: &PropertyKeys.isTransactionContext,
+                inObject: self
+            )
+        }
+    }
+    
+    @nonobjc
+    internal var isDataStackContext: Bool {
+        
+        get {
+            
+            let value: NSNumber? = cs_getAssociatedObjectForKey(
+                &PropertyKeys.isDataStackContext,
+                inObject: self
+            )
+            return value?.boolValue == true
+        }
+        set {
+            
+            cs_setAssociatedCopiedObject(
+                NSNumber(value: newValue),
+                forKey: &PropertyKeys.isDataStackContext,
+                inObject: self
+            )
+        }
+    }
+    
     @nonobjc
     internal func isRunningInAllowedQueue() -> Bool {
         
@@ -88,10 +127,10 @@ internal extension NSManagedObjectContext {
     }
     
     @nonobjc
-    internal func temporaryContextInTransactionWithConcurrencyType(concurrencyType: NSManagedObjectContextConcurrencyType) -> NSManagedObjectContext {
+    internal func temporaryContextInTransactionWithConcurrencyType(_ concurrencyType: NSManagedObjectContextConcurrencyType) -> NSManagedObjectContext {
         
         let context = NSManagedObjectContext(concurrencyType: concurrencyType)
-        context.parentContext = self
+        context.parent = self
         context.parentStack = self.parentStack
         context.setupForCoreStoreWithContextName("com.corestore.temporarycontext")
         context.shouldCascadeSavesToParent = (self.parentStack?.rootSavingContext == self)
@@ -105,7 +144,7 @@ internal extension NSManagedObjectContext {
       
         var result = SaveResult(hasChanges: false)
         
-        self.performBlockAndWait {
+        self.performAndWait {
             
             guard self.hasChanges else {
                 
@@ -123,20 +162,20 @@ internal extension NSManagedObjectContext {
                 let saveError = CoreStoreError(error)
                 CoreStore.log(
                     saveError,
-                    "Failed to save \(cs_typeName(NSManagedObjectContext))."
+                    "Failed to save \(cs_typeName(NSManagedObjectContext.self))."
                 )
                 result = SaveResult(saveError)
                 return
             }
             
-            if let parentContext = self.parentContext where self.shouldCascadeSavesToParent {
+            if let parentContext = self.parent, self.shouldCascadeSavesToParent {
                 
                 switch parentContext.saveSynchronously(waitForMerge: waitForMerge) {
                     
-                case .Success:
+                case .success:
                     result = SaveResult(hasChanges: true)
                     
-                case .Failure(let error):
+                case .failure(let error):
                     result = SaveResult(error)
                 }
             }
@@ -150,15 +189,15 @@ internal extension NSManagedObjectContext {
     }
     
     @nonobjc
-    internal func saveAsynchronouslyWithCompletion(completion: ((result: SaveResult) -> Void) = { _ in }) {
+    internal func saveAsynchronouslyWithCompletion(_ completion: @escaping ((_ result: SaveResult) -> Void) = { _ in }) {
         
-        self.performBlock {
+        self.perform {
             
             guard self.hasChanges else {
                 
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
-                    completion(result: SaveResult(hasChanges: false))
+                    completion(SaveResult(hasChanges: false))
                 }
                 return
             }
@@ -174,24 +213,24 @@ internal extension NSManagedObjectContext {
                 let saveError = CoreStoreError(error)
                 CoreStore.log(
                     saveError,
-                    "Failed to save \(cs_typeName(NSManagedObjectContext))."
+                    "Failed to save \(cs_typeName(NSManagedObjectContext.self))."
                 )
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
-                    completion(result: SaveResult(saveError))
+                    completion(SaveResult(saveError))
                 }
                 return
             }
             
-            if let parentContext = self.parentContext where self.shouldCascadeSavesToParent {
+            if self.shouldCascadeSavesToParent, let parentContext = self.parent {
                 
                 parentContext.saveAsynchronouslyWithCompletion(completion)
             }
             else {
                 
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
-                    completion(result: SaveResult(hasChanges: true))
+                    completion(SaveResult(hasChanges: true))
                 }
             }
         }
@@ -206,7 +245,7 @@ internal extension NSManagedObjectContext {
         }
         else {
             
-            self.registeredObjects.forEach { self.refreshObject($0, mergeChanges: true) }
+            self.registeredObjects.forEach { self.refresh($0, mergeChanges: true) }
         }
     }
     
@@ -217,5 +256,7 @@ internal extension NSManagedObjectContext {
         
         static var parentTransaction: Void?
         static var isSavingSynchronously: Void?
+        static var isTransactionContext: Void?
+        static var isDataStackContext: Void?
     }
 }
diff --git a/Sources/Internal/NSManagedObjectModel+Setup.swift b/Sources/Internal/NSManagedObjectModel+Setup.swift
index 2440d60..0d3c686 100644
--- a/Sources/Internal/NSManagedObjectModel+Setup.swift
+++ b/Sources/Internal/NSManagedObjectModel+Setup.swift
@@ -34,32 +34,34 @@ internal extension NSManagedObjectModel {
     // MARK: Internal
     
     @nonobjc
-    internal static func fromBundle(bundle: NSBundle, modelName: String, modelVersionHints: Set = []) -> NSManagedObjectModel {
+    internal static func fromBundle(_ bundle: Bundle, modelName: String, modelVersionHints: Set = []) -> NSManagedObjectModel {
         
-        guard let modelFilePath = bundle.pathForResource(modelName, ofType: "momd") else {
+        guard let modelFilePath = bundle.path(forResource: modelName, ofType: "momd") else {
             
+            // For users migrating from very old Xcode versions: Old xcdatamodel files are not contained inside xcdatamodeld (with a "d"), and will thus fail this check. If that was the case, create a new xcdatamodeld file and copy all contents into the new model.
             CoreStore.abort("Could not find \"\(modelName).momd\" from the bundle. \(bundle)")
         }
         
-        let modelFileURL = NSURL(fileURLWithPath: modelFilePath)
-        let versionInfoPlistURL = modelFileURL.URLByAppendingPathComponent("VersionInfo.plist", isDirectory: false)!
+        let modelFileURL = URL(fileURLWithPath: modelFilePath)
+        let versionInfoPlistURL = modelFileURL.appendingPathComponent("VersionInfo.plist", isDirectory: false)
         
-        guard let versionInfo = NSDictionary(contentsOfURL: versionInfoPlistURL),
+        guard let versionInfo = NSDictionary(contentsOf: versionInfoPlistURL),
             let versionHashes = versionInfo["NSManagedObjectModel_VersionHashes"] as? [String: AnyObject] else {
                 
-                CoreStore.abort("Could not load \(cs_typeName(NSManagedObjectModel)) metadata from path \"\(versionInfoPlistURL)\".")
+                CoreStore.abort("Could not load \(cs_typeName(NSManagedObjectModel.self)) metadata from path \"\(versionInfoPlistURL)\".")
         }
         
         let modelVersions = Set(versionHashes.keys)
         let currentModelVersion: String
-        if let plistModelVersion = versionInfo["NSManagedObjectModel_CurrentVersionName"] as? String where modelVersionHints.isEmpty || modelVersionHints.contains(plistModelVersion) {
+        if let plistModelVersion = versionInfo["NSManagedObjectModel_CurrentVersionName"] as? String,
+            modelVersionHints.isEmpty || modelVersionHints.contains(plistModelVersion) {
             
             currentModelVersion = plistModelVersion
         }
-        else if let resolvedVersion = modelVersions.intersect(modelVersionHints).first {
+        else if let resolvedVersion = modelVersions.intersection(modelVersionHints).first {
             
             CoreStore.log(
-                .Warning,
+                .warning,
                 message: "The MigrationChain leaf versions do not include the model file's current version. Resolving to version \"\(resolvedVersion)\"."
             )
             currentModelVersion = resolvedVersion
@@ -69,7 +71,7 @@ internal extension NSManagedObjectModel {
             if !modelVersionHints.isEmpty {
                 
                 CoreStore.log(
-                    .Warning,
+                    .warning,
                     message: "The MigrationChain leaf versions do not include any of the model file's embedded versions. Resolving to version \"\(resolvedVersion)\"."
                 )
             }
@@ -80,10 +82,10 @@ internal extension NSManagedObjectModel {
             CoreStore.abort("No model files were found in URL \"\(modelFileURL)\".")
         }
         
-        var modelVersionFileURL: NSURL?
+        var modelVersionFileURL: URL?
         for modelVersion in modelVersions {
             
-            let fileURL = modelFileURL.URLByAppendingPathComponent("\(modelVersion).mom", isDirectory: false)!
+            let fileURL = modelFileURL.appendingPathComponent("\(modelVersion).mom", isDirectory: false)
             
             if modelVersion == currentModelVersion {
                 
@@ -92,13 +94,13 @@ internal extension NSManagedObjectModel {
             }
             
             precondition(
-                NSManagedObjectModel(contentsOfURL: fileURL) != nil,
+                NSManagedObjectModel(contentsOf: fileURL) != nil,
                 "Could not find the \"\(modelVersion).mom\" version file for the model at URL \"\(modelFileURL)\"."
             )
         }
         
         if let modelVersionFileURL = modelVersionFileURL,
-            let rootModel = NSManagedObjectModel(contentsOfURL: modelVersionFileURL) {
+            let rootModel = NSManagedObjectModel(contentsOf: modelVersionFileURL) {
                 
                 rootModel.modelVersionFileURL = modelVersionFileURL
                 rootModel.modelVersions = modelVersions
@@ -106,7 +108,7 @@ internal extension NSManagedObjectModel {
                 return rootModel
         }
         
-        CoreStore.abort("Could not create an \(cs_typeName(NSManagedObjectModel)) from the model at URL \"\(modelFileURL)\".")
+        CoreStore.abort("Could not create an \(cs_typeName(NSManagedObjectModel.self)) from the model at URL \"\(modelFileURL)\".")
     }
     
     @nonobjc
@@ -152,7 +154,7 @@ internal extension NSManagedObjectModel {
     }
     
     @nonobjc
-    internal func entityNameForClass(entityClass: AnyClass) -> String {
+    internal func entityNameForClass(_ entityClass: AnyClass) -> String {
         
         return self.entityNameMapping[NSStringFromClass(entityClass)]!
     }
@@ -183,14 +185,14 @@ internal extension NSManagedObjectModel {
         }
         
         guard let modelFileURL = self.modelFileURL,
-            let modelVersions = self.modelVersions
-            where modelVersions.contains(modelVersion) else {
+            let modelVersions = self.modelVersions,
+            modelVersions.contains(modelVersion) else {
                 
                 return nil
         }
         
-        let versionModelFileURL = modelFileURL.URLByAppendingPathComponent("\(modelVersion).mom", isDirectory: false)
-        guard let model = NSManagedObjectModel(contentsOfURL: versionModelFileURL!) else {
+        let versionModelFileURL = modelFileURL.appendingPathComponent("\(modelVersion).mom", isDirectory: false)
+        guard let model = NSManagedObjectModel(contentsOf: versionModelFileURL) else {
             
             return nil
         }
@@ -202,15 +204,15 @@ internal extension NSManagedObjectModel {
     }
     
     @nonobjc
-    internal subscript(metadata: [String: AnyObject]) -> NSManagedObjectModel? {
+    internal subscript(metadata: [String: Any]) -> NSManagedObjectModel? {
         
-        guard let modelHashes = metadata[NSStoreModelVersionHashesKey] as? [String : NSData] else {
+        guard let modelHashes = metadata[NSStoreModelVersionHashesKey] as? [String : Data] else {
             
             return nil
         }
         for modelVersion in self.modelVersions ?? [] {
             
-            if let versionModel = self[modelVersion] where modelHashes == versionModel.entityVersionHashesByName {
+            if let versionModel = self[modelVersion], modelHashes == versionModel.entityVersionHashesByName {
                 
                 return versionModel
             }
@@ -222,16 +224,16 @@ internal extension NSManagedObjectModel {
     // MARK: Private
     
     @nonobjc
-    private var modelFileURL: NSURL? {
+    private var modelFileURL: URL? {
         
         get {
             
-            return self.modelVersionFileURL?.URLByDeletingLastPathComponent
+            return self.modelVersionFileURL?.deletingLastPathComponent()
         }
     }
     
     @nonobjc
-    private var modelVersionFileURL: NSURL? {
+    private var modelVersionFileURL: URL? {
         
         get {
             
@@ -239,12 +241,12 @@ internal extension NSManagedObjectModel {
                 &PropertyKeys.modelVersionFileURL,
                 inObject: self
             )
-            return value
+            return value as URL?
         }
         set {
             
             cs_setAssociatedCopiedObject(
-                newValue,
+                newValue as NSURL?,
                 forKey: &PropertyKeys.modelVersionFileURL,
                 inObject: self
             )
@@ -270,7 +272,7 @@ internal extension NSManagedObjectModel {
                 }
                 
                 let className = $0.managedObjectClassName
-                mapping[className] = entityName
+                mapping[className!] = entityName
             }
             cs_setAssociatedCopiedObject(
                 mapping as NSDictionary,
diff --git a/Sources/Internal/NSPersistentStore+Setup.swift b/Sources/Internal/NSPersistentStore+Setup.swift
index 4137819..085455b 100644
--- a/Sources/Internal/NSPersistentStore+Setup.swift
+++ b/Sources/Internal/NSPersistentStore+Setup.swift
@@ -66,15 +66,15 @@ internal extension NSPersistentStore {
 
 // MARK: - StorageObject
 
-private class StorageObject: NSObject {
+fileprivate class StorageObject: NSObject {
     
     // MARK: Private
     
     @nonobjc
-    private let storageInterface: StorageInterface?
+    fileprivate let storageInterface: StorageInterface?
     
     @nonobjc
-    private init(_ storage: StorageInterface?) {
+    fileprivate init(_ storage: StorageInterface?) {
         
         self.storageInterface = storage
     }
diff --git a/Sources/Internal/NSPersistentStoreCoordinator+Setup.swift b/Sources/Internal/NSPersistentStoreCoordinator+Setup.swift
index f59507b..04e79b2 100644
--- a/Sources/Internal/NSPersistentStoreCoordinator+Setup.swift
+++ b/Sources/Internal/NSPersistentStoreCoordinator+Setup.swift
@@ -26,134 +26,53 @@
 import Foundation
 import CoreData
 
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
-
 
 // MARK: - NSPersistentStoreCoordinator
 
 internal extension NSPersistentStoreCoordinator {
     
     @nonobjc
-    internal func performAsynchronously(closure: () -> Void) {
+    internal func performAsynchronously(_ closure: @escaping () -> Void) {
         
-        #if USE_FRAMEWORKS
-            
-            self.performBlock(closure)
-        #else
-            
-            if #available(iOS 8.0, *) {
-                
-                self.performBlock(closure)
-            }
-            else {
-                
-                self.lock()
-                GCDQueue.Default.async {
-                    
-                    closure()
-                    self.unlock()
-                }
-            }
-        #endif
+        self.perform(closure)
     }
     
     @nonobjc
-    internal func performSynchronously(closure: () -> T) -> T {
+    internal func performSynchronously(_ closure: @escaping () -> T) -> T {
         
         var result: T?
-        #if USE_FRAMEWORKS
+        self.performAndWait {
             
-            self.performBlockAndWait {
-                
-                result = closure()
-            }
-        #else
-            
-            if #available(iOS 8.0, *) {
-                
-                self.performBlockAndWait {
-                    
-                    result = closure()
-                }
-            }
-            else {
-                
-                self.lock()
-                cs_autoreleasepool {
-                    
-                    result = closure()
-                }
-                self.unlock()
-            }
-        #endif
-        
+            result = closure()
+        }
         return result!
     }
     
     @nonobjc
-    internal func performSynchronously(closure: () throws -> T) throws -> T {
+    internal func performSynchronously(_ closure: @escaping () throws -> T) throws -> T {
         
-        var closureError: ErrorType?
+        var closureError: Error?
         var result: T?
-        #if USE_FRAMEWORKS
+        self.performAndWait {
             
-            self.performBlockAndWait {
+            do {
                 
-                do {
-                    
-                    result = try closure()
-                }
-                catch {
-                    
-                    closureError = error
-                }
+                result = try closure()
             }
-        #else
-            
-            if #available(iOS 8.0, *) {
+            catch {
                 
-                self.performBlockAndWait {
-                    
-                    do {
-                        
-                        result = try closure()
-                    }
-                    catch {
-                        
-                        closureError = error
-                    }
-                }
+                closureError = error
             }
-            else {
-                
-                self.lock()
-                cs_autoreleasepool {
-                    
-                    do {
-                        
-                        result = try closure()
-                    }
-                    catch {
-                        
-                        closureError = error
-                    }
-                }
-                self.unlock()
-            }
-        #endif
-        
+        }
         if let closureError = closureError {
             
             throw closureError
         }
-        
         return result!
     }
     
     @nonobjc
-    internal func addPersistentStoreSynchronously(storeType: String, configuration: String?, URL storeURL: NSURL?, options: [NSObject : AnyObject]?) throws -> NSPersistentStore {
+    internal func addPersistentStoreSynchronously(_ storeType: String, configuration: String?, URL storeURL: URL?, options: [NSObject : AnyObject]?) throws -> NSPersistentStore {
         
         var store: NSPersistentStore?
         var storeError: NSError?
@@ -161,10 +80,10 @@ internal extension NSPersistentStoreCoordinator {
             
             do {
                 
-                store = try self.addPersistentStoreWithType(
-                    storeType,
-                    configuration: configuration,
-                    URL: storeURL,
+                store = try self.addPersistentStore(
+                    ofType: storeType,
+                    configurationName: configuration,
+                    at: storeURL,
                     options: options
                 )
             }
@@ -173,12 +92,10 @@ internal extension NSPersistentStoreCoordinator {
                 storeError = error as NSError
             }
         }
-        
         if let store = store {
             
             return store
         }
-        
         throw CoreStoreError(storeError)
     }
-}
\ No newline at end of file
+}
diff --git a/Sources/Internal/NotificationObserver.swift b/Sources/Internal/NotificationObserver.swift
index 460bc73..38f362e 100644
--- a/Sources/Internal/NotificationObserver.swift
+++ b/Sources/Internal/NotificationObserver.swift
@@ -34,18 +34,18 @@ internal final class NotificationObserver {
     
     let observer: NSObjectProtocol
     
-    init(notificationName: String, object: AnyObject?, queue: NSOperationQueue? = nil, closure: (note: NSNotification) -> Void) {
+    init(notificationName: Notification.Name, object: Any?, queue: OperationQueue? = nil, closure: @escaping (_ note: Notification) -> Void) {
         
-        self.observer = NSNotificationCenter.defaultCenter().addObserverForName(
-            notificationName,
+        self.observer = NotificationCenter.default.addObserver(
+            forName: notificationName,
             object: object,
             queue: queue,
-            usingBlock: closure
+            using: closure
         )
     }
     
     deinit {
         
-        NSNotificationCenter.defaultCenter().removeObserver(self.observer)
+        NotificationCenter.default.removeObserver(self.observer)
     }
 }
diff --git a/Sources/Logging/CoreStore+CustomDebugStringConvertible.swift b/Sources/Logging/CoreStore+CustomDebugStringConvertible.swift
index 9ed1647..283467c 100644
--- a/Sources/Logging/CoreStore+CustomDebugStringConvertible.swift
+++ b/Sources/Logging/CoreStore+CustomDebugStringConvertible.swift
@@ -49,7 +49,7 @@ extension AsynchronousDataTransaction: CustomDebugStringConvertible, CoreStoreDe
             ("supportsUndo", self.supportsUndo),
             ("bypassesQueueing", self.bypassesQueueing),
             ("isCommitted", self.isCommitted),
-            ("result", self.result)
+            ("result", self.result as Any)
         )
     }
 }
@@ -72,27 +72,27 @@ extension CloudStorageOptions: CustomDebugStringConvertible, CoreStoreDebugStrin
     public var coreStoreDumpString: String {
         
         var flags = [String]()
-        if self.contains(.RecreateLocalStoreOnModelMismatch) {
+        if self.contains(.recreateLocalStoreOnModelMismatch) {
             
-            flags.append(".RecreateLocalStoreOnModelMismatch")
+            flags.append(".recreateLocalStoreOnModelMismatch")
         }
-        if self.contains(.AllowSynchronousLightweightMigration) {
+        if self.contains(.allowSynchronousLightweightMigration) {
             
-            flags.append(".AllowSynchronousLightweightMigration")
+            flags.append(".allowSynchronousLightweightMigration")
         }
         switch flags.count {
             
         case 0:
-            return "[.None]"
+            return "[.none]"
             
         case 1:
             return "[.\(flags[0])]"
             
         default:
             var string = "[\n"
-            string.appendContentsOf(flags.joinWithSeparator(",\n"))
+            string.append(flags.joined(separator: ",\n"))
             string.indent(1)
-            string.appendContentsOf("\n]")
+            string.append("\n]")
             return string
         }
     }
@@ -117,30 +117,30 @@ extension CoreStoreError: CustomDebugStringConvertible, CoreStoreDebugStringConv
         
         let firstLine: String
         var info: DumpInfo = [
-            ("_domain", self._domain),
-            ("_code", self._code),
+            ("errorDomain", type(of: self).errorDomain),
+            ("errorCode", self.errorCode),
         ]
         switch self {
             
-        case .Unknown:
-            firstLine = ".Unknown"
+        case .unknown:
+            firstLine = ".unknown"
             
-        case .DifferentStorageExistsAtURL(let existingPersistentStoreURL):
-            firstLine = ".DifferentStorageExistsAtURL"
+        case .differentStorageExistsAtURL(let existingPersistentStoreURL):
+            firstLine = ".differentStorageExistsAtURL"
             info.append(("existingPersistentStoreURL", existingPersistentStoreURL))
             
-        case .MappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
-            firstLine = ".MappingModelNotFound"
+        case .mappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
+            firstLine = ".mappingModelNotFound"
             info.append(("localStoreURL", localStoreURL))
             info.append(("targetModel", targetModel))
             info.append(("targetModelVersion", targetModelVersion))
             
-        case .ProgressiveMigrationRequired(let localStoreURL):
-            firstLine = ".ProgressiveMigrationRequired"
+        case .progressiveMigrationRequired(let localStoreURL):
+            firstLine = ".progressiveMigrationRequired"
             info.append(("localStoreURL", localStoreURL))
             
-        case .InternalError(let NSError):
-            firstLine = ".InternalError"
+        case .internalError(let NSError):
+            firstLine = ".internalError"
             info.append(("NSError", NSError))
         }
         
@@ -254,8 +254,8 @@ extension ICloudStore: CustomDebugStringConvertible, CoreStoreDebugStringConvert
         
         return createFormattedString(
             "(", ")",
-            ("configuration", self.configuration),
-            ("storeOptions", self.storeOptions),
+            ("configuration", self.configuration as Any),
+            ("storeOptions", self.storeOptions as Any),
             ("cacheFileURL", self.cacheFileURL),
             ("cloudStorageOptions", self.cloudStorageOptions)
         )
@@ -283,8 +283,8 @@ extension InMemoryStore: CustomDebugStringConvertible, CoreStoreDebugStringConve
         
         return createFormattedString(
             "(", ")",
-            ("configuration", self.configuration),
-            ("storeOptions", self.storeOptions)
+            ("configuration", self.configuration as Any),
+            ("storeOptions", self.storeOptions as Any)
         )
     }
 }
@@ -309,7 +309,7 @@ extension Into: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
         return createFormattedString(
             "(", ")",
             ("entityClass", self.entityClass),
-            ("configuration", self.configuration),
+            ("configuration", self.configuration as Any),
             ("inferStoreIfPossible", self.inferStoreIfPossible)
         )
     }
@@ -334,8 +334,8 @@ extension LegacySQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringC
         
         return createFormattedString(
             "(", ")",
-            ("configuration", self.configuration),
-            ("storeOptions", self.storeOptions),
+            ("configuration", self.configuration as Any),
+            ("storeOptions", self.storeOptions as Any),
             ("fileURL", self.fileURL),
             ("mappingModelBundles", self.mappingModelBundles),
             ("localStorageOptions", self.localStorageOptions)
@@ -357,7 +357,7 @@ private struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConvertib
         return createFormattedString(
             "\"\(self.sectionInfo.name)\" (", ")",
             ("numberOfObjects", self.sectionInfo.numberOfObjects),
-            ("indexTitle", self.sectionInfo.indexTitle)
+            ("indexTitle", self.sectionInfo.indexTitle as Any)
         )
     }
 }
@@ -404,31 +404,31 @@ extension LocalStorageOptions: CustomDebugStringConvertible, CoreStoreDebugStrin
     public var coreStoreDumpString: String {
      
         var flags = [String]()
-        if self.contains(.RecreateStoreOnModelMismatch) {
+        if self.contains(.recreateStoreOnModelMismatch) {
             
-            flags.append(".RecreateStoreOnModelMismatch")
+            flags.append(".recreateStoreOnModelMismatch")
         }
-        if self.contains(.PreventProgressiveMigration) {
+        if self.contains(.preventProgressiveMigration) {
             
-            flags.append(".PreventProgressiveMigration")
+            flags.append(".preventProgressiveMigration")
         }
-        if self.contains(.AllowSynchronousLightweightMigration) {
+        if self.contains(.allowSynchronousLightweightMigration) {
             
-            flags.append(".AllowSynchronousLightweightMigration")
+            flags.append(".allowSynchronousLightweightMigration")
         }
         switch flags.count {
             
         case 0:
-            return "[.None]"
+            return "[.none]"
             
         case 1:
             return "[.\(flags[0])]"
             
         default:
             var string = "[\n"
-            string.appendContentsOf(flags.joinWithSeparator(",\n"))
+            string.append(flags.joined(separator: ",\n"))
             string.indent(1)
-            string.appendContentsOf("\n]")
+            string.append("\n]")
             return string
         }
     }
@@ -465,7 +465,7 @@ extension MigrationChain: CustomDebugStringConvertible, CoreStoreDebugStringConv
                 steps.append(nextVersion)
                 version = nextVersion
             }
-            paths.append(steps.joinWithSeparator(" → "))
+            paths.append(steps.joined(separator: " → "))
         }
         switch paths.count {
             
@@ -479,10 +479,10 @@ extension MigrationChain: CustomDebugStringConvertible, CoreStoreDebugStringConv
             var string = "["
             paths.forEach {
                 
-                string.appendContentsOf("\n\($0);")
+                string.append("\n\($0);")
             }
             string.indent(1)
-            string.appendContentsOf("\n]")
+            string.append("\n]")
             return string
         }
     }
@@ -507,15 +507,15 @@ extension MigrationResult: CustomDebugStringConvertible, CoreStoreDebugStringCon
         
         switch self {
             
-        case .Success(let migrationTypes):
+        case .success(let migrationTypes):
             return createFormattedString(
-                ".Success (", ")",
+                ".success (", ")",
                 ("migrationTypes", migrationTypes)
             )
             
-        case .Failure(let error):
+        case .failure(let error):
             return createFormattedString(
-                ".Failure (", ")",
+                ".failure (", ")",
                 ("error", error)
             )
         }
@@ -541,14 +541,14 @@ extension MigrationType: CustomDebugStringConvertible, CoreStoreDebugStringConve
         
         switch self {
             
-        case .None(let version):
-            return ".None (\"\(version)\")"
+        case .none(let version):
+            return ".none (\"\(version)\")"
             
-        case .Lightweight(let sourceVersion, let destinationVersion):
-            return ".Lightweight (\"\(sourceVersion)\" → \"\(destinationVersion)\")"
+        case .lightweight(let sourceVersion, let destinationVersion):
+            return ".lightweight (\"\(sourceVersion)\" → \"\(destinationVersion)\")"
             
-        case .Heavyweight(let sourceVersion, let destinationVersion):
-            return ".Heavyweight (\"\(sourceVersion)\" → \"\(destinationVersion)\")"
+        case .heavyweight(let sourceVersion, let destinationVersion):
+            return ".heavyweight (\"\(sourceVersion)\" → \"\(destinationVersion)\")"
         }
     }
 }
@@ -575,7 +575,7 @@ extension ObjectMonitor: CustomDebugStringConvertible, CoreStoreDebugStringConve
         return createFormattedString(
             "(", ")",
             ("isObjectDeleted", self.isObjectDeleted),
-            ("object", self.object)
+            ("object", self.object as Any)
         )
     }
 }
@@ -623,15 +623,15 @@ extension SaveResult: CustomDebugStringConvertible, CoreStoreDebugStringConverti
         
         switch self {
             
-        case .Success(let hasChanges):
+        case .success(let hasChanges):
             return createFormattedString(
-                ".Success (", ")",
+                ".success (", ")",
                 ("hasChanges", hasChanges)
             )
             
-        case .Failure(let error):
+        case .failure(let error):
             return createFormattedString(
-                ".Failure (", ")",
+                ".failure (", ")",
                 ("error", error)
             )
         }
@@ -708,24 +708,24 @@ extension SelectTerm: CustomDebugStringConvertible, CoreStoreDebugStringConverti
         
         switch self {
             
-        case ._Attribute(let keyPath):
+        case ._attribute(let keyPath):
             return createFormattedString(
-                ".Attribute (", ")",
+                ".attribute (", ")",
                 ("keyPath", keyPath)
             )
             
-        case ._Aggregate(let function, let keyPath, let alias, let nativeType):
+        case ._aggregate(let function, let keyPath, let alias, let nativeType):
             return createFormattedString(
-                ".Aggregate (", ")",
+                ".aggregate (", ")",
                 ("function", function),
                 ("keyPath", keyPath),
                 ("alias", alias),
                 ("nativeType", nativeType)
             )
             
-        case ._Identity(let alias, let nativeType):
+        case ._identity(let alias, let nativeType):
             return createFormattedString(
-                ".Identity (", ")",
+                ".identity (", ")",
                 ("alias", alias),
                 ("nativeType", nativeType)
             )
@@ -752,15 +752,15 @@ extension SetupResult: CustomDebugStringConvertible, CoreStoreDebugStringConvert
         
         switch self {
             
-        case .Success(let storage):
+        case .success(let storage):
             return createFormattedString(
-                ".Success (", ")",
+                ".success (", ")",
                 ("storage", storage)
             )
             
-        case .Failure(let error):
+        case .failure(let error):
             return createFormattedString(
-                ".Failure (", ")",
+                ".failure (", ")",
                 ("error", error)
             )
         }
@@ -786,8 +786,8 @@ extension SQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringConvert
         
         return createFormattedString(
             "(", ")",
-            ("configuration", self.configuration),
-            ("storeOptions", self.storeOptions),
+            ("configuration", self.configuration as Any),
+            ("storeOptions", self.storeOptions as Any),
             ("fileURL", self.fileURL),
             ("mappingModelBundles", self.mappingModelBundles),
             ("localStorageOptions", self.localStorageOptions)
@@ -818,7 +818,7 @@ extension SynchronousDataTransaction: CustomDebugStringConvertible, CoreStoreDeb
             ("supportsUndo", self.supportsUndo),
             ("bypassesQueueing", self.bypassesQueueing),
             ("isCommitted", self.isCommitted),
-            ("result", self.result)
+            ("result", self.result as Any)
         )
     }
 }
@@ -898,7 +898,7 @@ extension Where: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
 
 private typealias DumpInfo = [(key: String, value: Any)]
 
-private func formattedValue(any: Any) -> String {
+private func formattedValue(_ any: Any) -> String {
     
     switch any {
         
@@ -910,19 +910,19 @@ private func formattedValue(any: Any) -> String {
     }
 }
 
-private func formattedDebugDescription(any: Any) -> String {
+private func formattedDebugDescription(_ any: Any) -> String {
     
-    var string = "(\(String(reflecting: any.dynamicType))) "
-    string.appendContentsOf(formattedValue(any))
+    var string = "(\(String(reflecting: type(of: any)))) "
+    string.append(formattedValue(any))
     return string
 }
 
-private func createFormattedString(firstLine: String, _ lastLine: String, _ info: (key: String, value: Any)...) -> String {
+private func createFormattedString(_ firstLine: String, _ lastLine: String, _ info: (key: String, value: Any)...) -> String {
     
     return createFormattedString(firstLine, lastLine, info)
 }
 
-private func createFormattedString(firstLine: String, _ lastLine: String, _ info: [(key: String, value: Any)]) -> String {
+private func createFormattedString(_ firstLine: String, _ lastLine: String, _ info: [(key: String, value: Any)]) -> String {
     
     var string = firstLine
     for (key, value) in info {
@@ -930,34 +930,34 @@ private func createFormattedString(firstLine: String, _ lastLine: String, _ info
         string.appendDumpInfo(key, value)
     }
     string.indent(1)
-    string.appendContentsOf("\n\(lastLine)")
+    string.append("\n\(lastLine)")
     return string
 }
 
-private extension String {
+fileprivate extension String {
     
-    private static func indention(level: Int = 1) -> String {
+    fileprivate static func indention(_ level: Int = 1) -> String {
         
-        return String(count: level * 4, repeatedValue: Character(" "))
+        return String(repeating: " ", count: level * 4)
     }
     
-    private func trimSwiftModuleName() -> String {
+    fileprivate func trimSwiftModuleName() -> String {
         
         if self.hasPrefix("Swift.") {
             
-            return self.substringFromIndex("Swift.".endIndex)
+            return self.substring(from: "Swift.".endIndex)
         }
         return self
     }
     
-    private mutating func indent(level: Int) {
+    fileprivate mutating func indent(_ level: Int) {
         
-        self = self.stringByReplacingOccurrencesOfString("\n", withString: "\n\(String.indention(level))")
+        self = self.replacingOccurrences(of: "\n", with: "\n\(String.indention(level))")
     }
     
-    private mutating func appendDumpInfo(key: String, _ value: Any) {
+    fileprivate mutating func appendDumpInfo(_ key: String, _ value: Any) {
         
-        self.appendContentsOf("\n.\(key) = \(formattedValue(value));")
+        self.append("\n.\(key) = \(formattedValue(value));")
     }
 }
 
@@ -979,17 +979,17 @@ extension Array: CoreStoreDebugStringConvertible {
         var string = "\(self.count) item(s) ["
         if self.isEmpty {
             
-            string.appendContentsOf("]")
+            string.append("]")
             return string
         }
         else {
             
-            for (index, item) in self.enumerate() {
+            for (index, item) in self.enumerated() {
                 
-                string.appendContentsOf("\n\(index) = \(formattedValue(item));")
+                string.append("\n\(index) = \(formattedValue(item));")
             }
             string.indent(1)
-            string.appendContentsOf("\n]")
+            string.append("\n]")
             return string
         }
     }
@@ -1002,17 +1002,17 @@ extension Dictionary: CoreStoreDebugStringConvertible {
         var string = "\(self.count) key-value(s) ["
         if self.isEmpty {
             
-            string.appendContentsOf("]")
+            string.append("]")
             return string
         }
         else {
             
             for (key, value) in self {
                 
-                string.appendContentsOf("\n\(formattedValue(key)) = \(formattedValue(value));")
+                string.append("\n\(formattedValue(key)) = \(formattedValue(value));")
             }
             string.indent(1)
-            string.appendContentsOf("\n]")
+            string.append("\n]")
             return string
         }
     }
@@ -1025,21 +1025,21 @@ extension NSAttributeDescription: CoreStoreDebugStringConvertible {
         return createFormattedString(
             "(", ")",
             ("attributeType", self.attributeType),
-            ("attributeValueClassName", self.attributeValueClassName),
-            ("defaultValue", self.defaultValue),
-            ("valueTransformerName", self.valueTransformerName),
+            ("attributeValueClassName", self.attributeValueClassName as Any),
+            ("defaultValue", self.defaultValue as Any),
+            ("valueTransformerName", self.valueTransformerName as Any),
             ("allowsExternalBinaryDataStorage", self.allowsExternalBinaryDataStorage),
-            ("entity.name", self.entity.name),
+            ("entity.name", self.entity.name as Any),
             ("name", self.name),
-            ("optional", self.optional),
-            ("transient", self.transient),
-            ("userInfo", self.userInfo),
-            ("indexed", self.indexed),
+            ("isOptional", self.isOptional),
+            ("isTransient", self.isTransient),
+            ("userInfo", self.userInfo as Any),
+            ("isIndexed", self.isIndexed),
             ("versionHash", self.versionHash),
-            ("versionHashModifier", self.versionHashModifier),
-            ("indexedBySpotlight", self.indexedBySpotlight),
-            ("storedInExternalRecord", self.storedInExternalRecord),
-            ("renamingIdentifier", self.renamingIdentifier)
+            ("versionHashModifier", self.versionHashModifier as Any),
+            ("isIndexedBySpotlight", self.isIndexedBySpotlight),
+            ("isStoredInExternalRecord", self.isStoredInExternalRecord),
+            ("renamingIdentifier", self.renamingIdentifier as Any)
         )
     }
 }
@@ -1050,28 +1050,28 @@ extension NSAttributeType: CoreStoreDebugStringConvertible {
         
         switch self {
             
-        case .UndefinedAttributeType:       return ".UndefinedAttributeType"
-        case .Integer16AttributeType:       return ".Integer16AttributeType"
-        case .Integer32AttributeType:       return ".Integer32AttributeType"
-        case .Integer64AttributeType:       return ".Integer64AttributeType"
-        case .DecimalAttributeType:         return ".DecimalAttributeType"
-        case .DoubleAttributeType:          return ".DoubleAttributeType"
-        case .FloatAttributeType:           return ".FloatAttributeType"
-        case .StringAttributeType:          return ".StringAttributeType"
-        case .BooleanAttributeType:         return ".BooleanAttributeType"
-        case .DateAttributeType:            return ".DateAttributeType"
-        case .BinaryDataAttributeType:      return ".BinaryDataAttributeType"
-        case .TransformableAttributeType:   return ".TransformableAttributeType"
-        case .ObjectIDAttributeType:        return ".ObjectIDAttributeType"
+        case .undefinedAttributeType:       return ".undefinedAttributeType"
+        case .integer16AttributeType:       return ".integer16AttributeType"
+        case .integer32AttributeType:       return ".integer32AttributeType"
+        case .integer64AttributeType:       return ".integer64AttributeType"
+        case .decimalAttributeType:         return ".decimalAttributeType"
+        case .doubleAttributeType:          return ".doubleAttributeType"
+        case .floatAttributeType:           return ".floatAttributeType"
+        case .stringAttributeType:          return ".stringAttributeType"
+        case .booleanAttributeType:         return ".booleanAttributeType"
+        case .dateAttributeType:            return ".dateAttributeType"
+        case .binaryDataAttributeType:      return ".binaryDataAttributeType"
+        case .transformableAttributeType:   return ".transformableAttributeType"
+        case .objectIDAttributeType:        return ".objectIDAttributeType"
         }
     }
 }
 
-extension NSBundle: CoreStoreDebugStringConvertible {
+extension Bundle: CoreStoreDebugStringConvertible {
     
     public var coreStoreDumpString: String {
         
-        return "\(self.bundleIdentifier.flatMap({ "\"\($0)\"" }) ?? "") (\(self.bundleURL.lastPathComponent ?? ""))"
+        return "\(self.bundleIdentifier.flatMap({ "\"\($0)\"" }) ?? "") (\(self.bundleURL.lastPathComponent))"
     }
 }
 
@@ -1081,10 +1081,10 @@ extension NSDeleteRule: CoreStoreDebugStringConvertible {
         
         switch self {
             
-        case .NoActionDeleteRule:   return ".NoActionDeleteRule"
-        case .NullifyDeleteRule:    return ".NullifyDeleteRule"
-        case .CascadeDeleteRule:    return ".CascadeDeleteRule"
-        case .DenyDeleteRule:       return ".DenyDeleteRule"
+        case .noActionDeleteRule:   return ".noActionDeleteRule"
+        case .nullifyDeleteRule:    return ".nullifyDeleteRule"
+        case .cascadeDeleteRule:    return ".cascadeDeleteRule"
+        case .denyDeleteRule:       return ".denyDeleteRule"
         }
     }
 }
@@ -1095,15 +1095,15 @@ extension NSEntityDescription: CoreStoreDebugStringConvertible {
         
         var info: DumpInfo = [
             ("managedObjectClassName", self.managedObjectClassName!),
-            ("name", self.name),
-            ("abstract", self.abstract),
-            ("superentity?.name", self.superentity?.name),
+            ("name", self.name as Any),
+            ("isAbstract", self.isAbstract),
+            ("superentity?.name", self.superentity?.name as Any),
             ("subentities", self.subentities.map({ $0.name })),
             ("properties", self.properties),
-            ("userInfo", self.userInfo),
+            ("userInfo", self.userInfo as Any),
             ("versionHash", self.versionHash),
-            ("versionHashModifier", self.versionHashModifier),
-            ("renamingIdentifier", self.renamingIdentifier),
+            ("versionHashModifier", self.versionHashModifier as Any),
+            ("renamingIdentifier", self.renamingIdentifier as Any),
             ("compoundIndexes", self.compoundIndexes)
         ]
         if #available(iOS 9.0, OSXApplicationExtension 10.11, OSX 10.11, *) {
@@ -1147,10 +1147,10 @@ extension NSManagedObjectID: CoreStoreDebugStringConvertible {
     public var coreStoreDumpString: String {
         
         return createFormattedString(
-            "\(self.URIRepresentation().coreStoreDumpString) (", ")",
-            ("entity.name", self.entity.name),
-            ("temporaryID", self.temporaryID),
-            ("persistentStore?.URL", self.persistentStore?.URL)
+            "\(self.uriRepresentation().coreStoreDumpString) (", ")",
+            ("entity.name", self.entity.name as Any),
+            ("isTemporaryID", self.isTemporaryID as Any),
+            ("persistentStore?.url", self.persistentStore?.url as Any)
         )
     }
 }
@@ -1177,24 +1177,24 @@ extension NSRelationshipDescription: CoreStoreDebugStringConvertible {
         
         return createFormattedString(
             "(", ")",
-            ("destinationEntity?.name", self.destinationEntity?.name),
-            ("inverseRelationship?.name", self.inverseRelationship?.name),
+            ("destinationEntity?.name", self.destinationEntity?.name as Any),
+            ("inverseRelationship?.name", self.inverseRelationship?.name as Any),
             ("minCount", self.minCount),
             ("maxCount", self.maxCount),
             ("deleteRule", self.deleteRule),
-            ("toMany", self.toMany),
-            ("ordered", self.ordered),
-            ("entity.name", self.entity.name),
+            ("isToMany", self.isToMany),
+            ("isOrdered", self.isOrdered),
+            ("entity.name", self.entity.name as Any),
             ("name", self.name),
-            ("optional", self.optional),
-            ("transient", self.transient),
-            ("userInfo", self.userInfo),
-            ("indexed", self.indexed),
+            ("isOptional", self.isOptional),
+            ("isTransient", self.isTransient),
+            ("userInfo", self.userInfo as Any),
+            ("isIndexed", self.isIndexed),
             ("versionHash", self.versionHash),
-            ("versionHashModifier", self.versionHashModifier),
-            ("indexedBySpotlight", self.indexedBySpotlight),
-            ("storedInExternalRecord", self.storedInExternalRecord),
-            ("renamingIdentifier", self.renamingIdentifier)
+            ("versionHashModifier", self.versionHashModifier as Any),
+            ("isIndexedBySpotlight", self.isIndexedBySpotlight),
+            ("isStoredInExternalRecord", self.isStoredInExternalRecord),
+            ("renamingIdentifier", self.renamingIdentifier as Any)
         )
     }
 }
@@ -1205,14 +1205,14 @@ extension NSSortDescriptor: CoreStoreDebugStringConvertible {
         
         return createFormattedString(
             "(", ")",
-            ("key", self.key),
+            ("key", self.key as Any),
             ("ascending", self.ascending),
-            ("selector", self.selector)
+            ("selector", self.selector as Any)
         )
     }
 }
 
-extension NSURL: CoreStoreDebugStringConvertible {
+extension URL: CoreStoreDebugStringConvertible {
     
     public var coreStoreDumpString: String {
         
@@ -1236,7 +1236,7 @@ extension Selector: CoreStoreDebugStringConvertible {
     
     public var coreStoreDumpString: String {
         
-        return self == nil ? "nil" : "\"\(self)\""
+        return "\"\(self)\""
     }
 }
 
diff --git a/Sources/Logging/CoreStore+Logging.swift b/Sources/Logging/CoreStore+Logging.swift
index 35d6097..6102cf8 100644
--- a/Sources/Logging/CoreStore+Logging.swift
+++ b/Sources/Logging/CoreStore+Logging.swift
@@ -38,7 +38,7 @@ public extension CoreStore {
     
     // MARK: Internal
     
-    internal static func log(level: LogLevel, message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
+    internal static func log(_ level: LogLevel, message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
         
         self.logger.log(
             level: level,
@@ -49,7 +49,7 @@ public extension CoreStore {
         )
     }
     
-    internal static func log(error: CoreStoreError, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
+    internal static func log(_ error: CoreStoreError, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
         
         self.logger.log(
             error: error,
@@ -60,7 +60,7 @@ public extension CoreStore {
         )
     }
     
-    internal static func assert(@autoclosure condition: () -> Bool, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
+    internal static func assert( _ condition: @autoclosure () -> Bool, _ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
         
         self.logger.assert(
             condition,
@@ -71,8 +71,7 @@ public extension CoreStore {
         )
     }
     
-    @noreturn
-    internal static func abort(message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
+    internal static func abort(_ message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) -> Never  {
         
         self.logger.abort(
             message,
diff --git a/Sources/Logging/CoreStoreLogger.swift b/Sources/Logging/CoreStoreLogger.swift
index b6f4ea5..57e1714 100644
--- a/Sources/Logging/CoreStoreLogger.swift
+++ b/Sources/Logging/CoreStoreLogger.swift
@@ -33,17 +33,17 @@ import Foundation
  */
 public enum LogLevel {
     
-    case Trace
-    case Notice
-    case Warning
-    case Fatal
+    case trace
+    case notice
+    case warning
+    case fatal
 }
 
 
 // MARK: - CoreStoreLogger
 
 /**
- Custom loggers should implement the `CoreStoreLogger` protocol and pass its instance to `CoreStore.logger`. Calls to `log(...)`, `handleError(...)`, and `assert(...)` are not tied to a specific queue/thread, so it is the implementer's job to handle thread-safety.
+ Custom loggers should implement the `CoreStoreLogger` protocol and pass its instance to `CoreStore.logger`. Calls to `log(...)`, `assert(...)`, and `abort(...)` are not tied to a specific queue/thread, so it is the implementer's job to handle thread-safety.
  */
 public protocol CoreStoreLogger {
     
@@ -56,7 +56,7 @@ public protocol CoreStoreLogger {
      - parameter lineNumber: the source line number
      - parameter functionName: the source function name
      */
-    func log(level level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
+    func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
     
     /**
      Handles errors sent by the `CoreStore` framework.
@@ -67,7 +67,7 @@ public protocol CoreStoreLogger {
      - parameter lineNumber: the source line number
      - parameter functionName: the source function name
      */
-    func log(error error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
+    func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
     
     /**
      Handles assertions made throughout the `CoreStore` framework.
@@ -78,41 +78,23 @@ public protocol CoreStoreLogger {
      - parameter lineNumber: the source line number
      - parameter functionName: the source function name
      */
-    func assert(@autoclosure condition: () -> Bool, @autoclosure message: () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
+    func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
     
     /**
      Handles fatal errors made throughout the `CoreStore` framework. The app wil terminate after this method is called.
-     - Important: Implementers may guarantee that the function doesn't return, either by calling another `@noreturn` function such as `fatalError()` or `abort()`, or by raising an exception. If the implementation does not terminate the app, CoreStore will call an internal `fatalError()` to do so.
+     - Important: Implementers may guarantee that the function doesn't return, either by calling another `Never` function such as `fatalError()` or `abort()`, or by raising an exception. If the implementation does not terminate the app, CoreStore will call an internal `fatalError()` to do so.
      
      - parameter message: the fatal error message
      - parameter fileName: the source file name
      - parameter lineNumber: the source line number
      - parameter functionName: the source function name
      */
-    func abort(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
-    
-    
-    // MARK: Deprecated
-    
-    /**
-     Deprecated. Use `log(error:message:fileName:lineNumber:functionName:)` instead.
-     */
-    @available(*, deprecated=2.0.0, message="Use log(error:message:fileName:lineNumber:functionName:) instead.")
-    func handleError(error error: NSError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
+    func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
 }
 
 extension CoreStoreLogger {
     
-    /**
-     Deprecated. Use `log(error:message:fileName:lineNumber:functionName:)` instead.
-     */
-    @available(*, deprecated=2.0.0, message="Use log(error:message:fileName:lineNumber:functionName:) instead.")
-    public func handleError(error error: NSError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
-    
-        self.log(error: error.bridgeToSwift, message: message, fileName: fileName, lineNumber: lineNumber, functionName: functionName)
-    }
-    
-    public func abort(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
+    public func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
         
         Swift.fatalError(message, file: fileName, line: UInt(lineNumber))
     }
diff --git a/Sources/Logging/DefaultLogger.swift b/Sources/Logging/DefaultLogger.swift
index bf79b40..fcfc486 100644
--- a/Sources/Logging/DefaultLogger.swift
+++ b/Sources/Logging/DefaultLogger.swift
@@ -30,10 +30,6 @@ import Foundation
 
 /**
  The `DefaultLogger` is a basic implementation of the `CoreStoreLogger` protocol.
- 
- - The `log(...)` method calls `print(...)` to print the level, source file name, line number, function name, and the log message.
- - The `handleError(...)` method calls `print(...)` to print the source file name, line number, function name, and the error message.
- - The `assert(...)` method calls `assert(...)` on the arguments.
  */
 public final class DefaultLogger: CoreStoreLogger {
     
@@ -51,30 +47,30 @@ public final class DefaultLogger: CoreStoreLogger {
      - parameter lineNumber: the source line number
      - parameter functionName: the source function name
      */
-    public func log(level level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
+    public func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
         
         #if DEBUG
             let icon: String
             let levelString: String
             switch level {
                 
-            case .Trace:
+            case .trace:
                 icon = "🔹"
                 levelString = "Trace"
                 
-            case .Notice:
+            case .notice:
                 icon = "🔸"
                 levelString = "Notice"
                 
-            case .Warning:
+            case .warning:
                 icon = "⚠️"
                 levelString = "Warning"
                 
-            case .Fatal:
+            case .fatal:
                 icon = "❗"
                 levelString = "Fatal"
             }
-            Swift.print("\(icon) [CoreStore: \(levelString)] \((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n  ↪︎ \(message)\n")
+            Swift.print("\(icon) [CoreStore: \(levelString)] \((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n  ↪︎ \(message)\n")
         #endif
     }
     
@@ -87,10 +83,10 @@ public final class DefaultLogger: CoreStoreLogger {
      - parameter lineNumber: the source line number
      - parameter functionName: the source function name
      */
-    public func log(error error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
+    public func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
         
         #if DEBUG
-            Swift.print("⚠️ [CoreStore: Error] \((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n  ↪︎ \(message)\n    \(error)\n")
+            Swift.print("⚠️ [CoreStore: Error] \((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n  ↪︎ \(message)\n    \(error)\n")
         #endif
     }
     
@@ -103,30 +99,30 @@ public final class DefaultLogger: CoreStoreLogger {
      - parameter lineNumber: the source line number
      - parameter functionName: the source function name
      */
-    public func assert(@autoclosure condition: () -> Bool, @autoclosure message: () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
+    public func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
         
         #if DEBUG
             if condition() {
                 
                 return
             }
-            Swift.print("❗ [CoreStore: Assertion Failure] \((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n  ↪︎ \(message())\n")
+            Swift.print("❗ [CoreStore: Assertion Failure] \((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n  ↪︎ \(message())\n")
             Swift.fatalError(file: fileName, line: UInt(lineNumber))
         #endif
     }
     
     /**
      Handles fatal errors made throughout the `CoreStore` framework.
-     - Important: This method should be marked `@noreturn` and implementers should guarantee that the function doesn't, either by calling another `@noreturn` function such as `fatalError()` or `abort()`, or by raising an exception.
+     - Important: Implementers should guarantee that this function doesn't return, either by calling another `Never` function such as `fatalError()` or `abort()`, or by raising an exception.
      
      - parameter message: the fatal error message
      - parameter fileName: the source file name
      - parameter lineNumber: the source line number
      - parameter functionName: the source function name
      */
-    public func abort(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
+    public func abort(_ message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
         
-        Swift.print("❗ [CoreStore: Fatal Error] \((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n  ↪︎ \(message)\n")
+        Swift.print("❗ [CoreStore: Fatal Error] \((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n  ↪︎ \(message)\n")
         Swift.fatalError(file: fileName, line: UInt(lineNumber))
     }
 }
diff --git a/Sources/Migrating/CoreStore+Migration.swift b/Sources/Migrating/CoreStore+Migration.swift
index d637c21..54ed936 100644
--- a/Sources/Migrating/CoreStore+Migration.swift
+++ b/Sources/Migrating/CoreStore+Migration.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - CoreStore
@@ -41,17 +38,16 @@ public extension CoreStore {
          InMemoryStore.self,
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storeType: the storage type
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
      */
-    public static func addStorage(storeType: T.Type, completion: (SetupResult) -> Void) {
+    public static func addStorage(_ storeType: T.Type, completion: @escaping (SetupResult) -> Void) where T: DefaultInitializableStore {
         
         self.defaultStack.addStorage(storeType.init(), completion: completion)
     }
@@ -63,17 +59,16 @@ public extension CoreStore {
          InMemoryStore(configuration: "Config1"),
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storage: the storage
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
      */
-    public static func addStorage(storage: T, completion: (SetupResult) -> Void) {
+    public static func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void) {
         
         self.defaultStack.addStorage(storage, completion: completion)
     }
@@ -85,18 +80,17 @@ public extension CoreStore {
          SQLiteStore.self,
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storeType: the local storage type
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
-     - returns: an `NSProgress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
+     - returns: a `Progress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
      */
-    public static func addStorage(storeType: T.Type, completion: (SetupResult) -> Void) -> NSProgress? {
+    public static func addStorage(_ storeType: T.Type, completion: @escaping (SetupResult) -> Void) -> Progress? where T: DefaultInitializableStore {
         
         return self.defaultStack.addStorage(storeType.init(), completion: completion)
     }
@@ -108,18 +102,17 @@ public extension CoreStore {
          SQLiteStore(fileName: "core_data.sqlite", configuration: "Config1"),
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storage: the local storage
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
-     - returns: an `NSProgress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
+     - returns: a `Progress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
      */
-    public static func addStorage(storage: T, completion: (SetupResult) -> Void) -> NSProgress? {
+    public static func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void) -> Progress? {
         
         return self.defaultStack.addStorage(storage, completion: completion)
     }
@@ -133,7 +126,7 @@ public extension CoreStore {
          ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
          ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
          configuration: "Config1",
-         cloudStorageOptions: .RecreateLocalStoreOnModelMismatch
+         cloudStorageOptions: .recreateLocalStoreOnModelMismatch
      ) else {
          // iCloud is not available on the device
          return
@@ -142,17 +135,16 @@ public extension CoreStore {
          storage,
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storage: the cloud storage
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `CloudStorage` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `CloudStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
      */
-    public static func addStorage(storage: T, completion: (SetupResult) -> Void) {
+    public static func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void) {
         
         self.defaultStack.addStorage(storage, completion: completion)
     }
@@ -161,11 +153,11 @@ public extension CoreStore {
      Migrates a local storage to match the `defaultStack`'s managed object model version. This method does NOT add the migrated store to the data stack.
 
      - parameter storage: the local storage
-     - parameter completion: the closure to be executed on the main queue when the migration completes, either due to success or failure. The closure's `MigrationResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a `.Failure` result if an error occurs asynchronously.
+     - parameter completion: the closure to be executed on the main queue when the migration completes, either due to success or failure. The closure's `MigrationResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a `.failure` result if an error occurs asynchronously.
      - throws: a `CoreStoreError` value indicating the failure
-     - returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
+     - returns: a `Progress` instance if a migration has started, or `nil` is no migrations are required
      */
-    public static func upgradeStorageIfNeeded(storage: T, completion: (MigrationResult) -> Void) throws -> NSProgress? {
+    public static func upgradeStorageIfNeeded(_ storage: T, completion: @escaping (MigrationResult) -> Void) throws -> Progress? {
         
         return try self.defaultStack.upgradeStorageIfNeeded(storage, completion: completion)
     }
@@ -177,110 +169,8 @@ public extension CoreStore {
      - throws: a `CoreStoreError` value indicating the failure
      - returns: a `MigrationType` array indicating the migration steps required for the store, or an empty array if the file does not exist yet. Otherwise, an error is thrown if either inspection of the store failed, or if no mapping model was found/inferred.
      */
-    @warn_unused_result
-    public static func requiredMigrationsForStorage(storage: T) throws -> [MigrationType] {
+    public static func requiredMigrationsForStorage(_ storage: T) throws -> [MigrationType] {
         
         return try self.defaultStack.requiredMigrationsForStorage(storage)
     }
-    
-    
-    // MARK: Deprecated
-    
-    /**
-     Deprecated. Use `addSQLiteStore(_:completion:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use addSQLiteStore(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public static func addSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
-        
-        return try self.defaultStack.addSQLiteStore(
-            fileName: fileName,
-            configuration: configuration,
-            mappingModelBundles: mappingModelBundles,
-            resetStoreOnModelMismatch: resetStoreOnModelMismatch,
-            completion: completion
-        )
-    }
-    
-    /**
-     Deprecated. Use `addSQLiteStore(_:completion:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use addSQLiteStore(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public static func addSQLiteStore(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = NSBundle.allBundles(), resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
-        
-        return try self.defaultStack.addSQLiteStore(
-            fileURL: fileURL,
-            configuration: configuration,
-            mappingModelBundles: mappingModelBundles,
-            resetStoreOnModelMismatch: resetStoreOnModelMismatch,
-            completion: completion
-        )
-    }
-    
-    /**
-     Deprecated. Use `upgradeStorageIfNeeded(_:completion:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use upgradeStorageIfNeeded(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public static func upgradeSQLiteStoreIfNeeded(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, completion: (MigrationResult) -> Void) throws -> NSProgress? {
-        
-        return try self.defaultStack.upgradeSQLiteStoreIfNeeded(
-            fileName: fileName,
-            configuration: configuration,
-            mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
-            completion: completion
-        )
-    }
-    
-    /**
-     Deprecated. Use `upgradeStorageIfNeeded(_:completion:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use upgradeStorageIfNeeded(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public static func upgradeSQLiteStoreIfNeeded(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, completion: (MigrationResult) -> Void) throws -> NSProgress? {
-        
-        return try self.defaultStack.upgradeSQLiteStoreIfNeeded(
-            fileURL: fileURL,
-            configuration: configuration,
-            mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
-            completion: completion
-        )
-    }
-    
-    /**
-     Deprecated. Use `requiredMigrationsForStorage(_:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use requiredMigrationsForStorage(_:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    @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(
-            fileName: fileName,
-            configuration: configuration,
-            mappingModelBundles: mappingModelBundles
-        )
-    }
-    
-    /**
-     Deprecated. Use `requiredMigrationsForStorage(_:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use requiredMigrationsForStorage(_:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    @warn_unused_result
-    public static func requiredMigrationsForSQLiteStore(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles() as [NSBundle]) throws -> [MigrationType] {
-        
-        return try self.defaultStack.requiredMigrationsForSQLiteStore(
-            fileURL: fileURL,
-            configuration: configuration,
-            mappingModelBundles: mappingModelBundles
-        )
-    }
 }
diff --git a/Sources/Migrating/DataStack+Migration.swift b/Sources/Migrating/DataStack+Migration.swift
index 9935dea..07d1a6c 100644
--- a/Sources/Migrating/DataStack+Migration.swift
+++ b/Sources/Migrating/DataStack+Migration.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - DataStack
@@ -41,17 +38,16 @@ public extension DataStack {
          InMemoryStore.self,
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storeType: the storage type
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
      */
-    public func addStorage(storeType: T.Type, completion: (SetupResult) -> Void) {
+    public func addStorage(_ storeType: T.Type, completion: @escaping (SetupResult) -> Void) where T: DefaultInitializableStore {
         
         self.addStorage(storeType.init(), completion: completion)
     }
@@ -63,23 +59,22 @@ public extension DataStack {
          InMemoryStore(configuration: "Config1"),
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storage: the storage
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `StorageInterface` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `StorageInterface` was already added at the same URL and with the same configuration.
      */
-    public func addStorage(storage: T, completion: (SetupResult) -> Void) {
+    public func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void) {
         
         self.coordinator.performAsynchronously {
             
             if let _ = self.persistentStoreForStorage(storage) {
                 
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
                     completion(SetupResult(storage))
                 }
@@ -88,13 +83,13 @@ public extension DataStack {
             
             do {
                 
-                try self.createPersistentStoreFromStorage(
+                _ = try self.createPersistentStoreFromStorage(
                     storage,
                     finalURL: nil,
                     finalStoreOptions: storage.storeOptions
                 )
                 
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
                     completion(SetupResult(storage))
                 }
@@ -106,7 +101,7 @@ public extension DataStack {
                     storeError,
                     "Failed to add \(cs_typeName(storage)) to the stack."
                 )
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
                     completion(SetupResult(storeError))
                 }
@@ -121,20 +116,19 @@ public extension DataStack {
          SQLiteStore.self,
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storeType: the local storage type
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
-     - returns: an `NSProgress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
+     - returns: a `Progress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
      */
-    public func addStorage(storeType: T.Type, completion: (SetupResult) -> Void) -> NSProgress? {
+    public func addStorage(_ storeType: T.Type, completion: @escaping (SetupResult) -> Void) -> Progress? where T: DefaultInitializableStore {
         
-        return self.addStorage(storeType.init(), completion: completion)
+        return self.addStorage(storeType.init() as! T.Type, completion: completion)
     }
     
     /**
@@ -144,22 +138,21 @@ public extension DataStack {
          SQLiteStore(fileName: "core_data.sqlite", configuration: "Config1"),
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storage: the local storage
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
-     - returns: an `NSProgress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `LocalStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
+     - returns: a `Progress` instance if a migration has started, or `nil` if either no migrations are required or if a failure occured.
      */
-    public func addStorage(storage: T, completion: (SetupResult) -> Void) -> NSProgress? {
+    public func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void) -> Progress? {
         
         let fileURL = storage.fileURL
         CoreStore.assert(
-            fileURL.fileURL,
+            fileURL.isFileURL,
             "The specified URL for the \(cs_typeName(storage)) is invalid: \"\(fileURL)\""
         )
         
@@ -167,31 +160,31 @@ public extension DataStack {
             
             if let _ = self.persistentStoreForStorage(storage) {
                 
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
                     completion(SetupResult(storage))
                 }
                 return nil
             }
             
-            if let persistentStore = self.coordinator.persistentStoreForURL(fileURL) {
+            if let persistentStore = self.coordinator.persistentStore(for: fileURL as URL) {
                 
-                if let existingStorage = persistentStore.storageInterface as? T
-                    where storage.matchesPersistentStore(persistentStore) {
+                if let existingStorage = persistentStore.storageInterface as? T,
+                    storage.matchesPersistentStore(persistentStore) {
                     
-                    GCDQueue.Main.async {
+                    DispatchQueue.main.async {
                         
                         completion(SetupResult(existingStorage))
                     }
                     return nil
                 }
                 
-                let error = CoreStoreError.DifferentStorageExistsAtURL(existingPersistentStoreURL: fileURL)
+                let error = CoreStoreError.differentStorageExistsAtURL(existingPersistentStoreURL: fileURL)
                 CoreStore.log(
                     error,
-                    "Failed to add \(cs_typeName(storage)) at \"\(fileURL)\" because a different \(cs_typeName(NSPersistentStore)) at that URL already exists."
+                    "Failed to add \(cs_typeName(storage)) at \"\(fileURL)\" because a different \(cs_typeName(NSPersistentStore.self)) at that URL already exists."
                 )
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
                     completion(SetupResult(error))
                 }
@@ -200,15 +193,15 @@ public extension DataStack {
             
             do {
                 
-                try NSFileManager.defaultManager().createDirectoryAtURL(
-                    fileURL.URLByDeletingLastPathComponent!,
+                try FileManager.default.createDirectory(
+                    at: fileURL.deletingLastPathComponent(),
                     withIntermediateDirectories: true,
                     attributes: nil
                 )
                 
-                let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(
-                    storage.dynamicType.storeType,
-                    URL: fileURL,
+                let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
+                    ofType: type(of: storage).storeType,
+                    at: fileURL as URL,
                     options: storage.storeOptions
                 )
                 
@@ -217,16 +210,19 @@ public extension DataStack {
                     metadata: metadata,
                     completion: { (result) -> Void in
                         
-                        if case .Failure(.InternalError(let error)) = result {
+                        if case .failure(.internalError(let error)) = result {
                             
-                            if storage.localStorageOptions.contains(.RecreateStoreOnModelMismatch) && error.isCoreDataMigrationError {
+                            if storage.localStorageOptions.contains(.recreateStoreOnModelMismatch) && error.isCoreDataMigrationError {
                                 
                                 do {
                                     
-                                    _ = try storage.eraseStorageAndWait(soureModel: self.model[metadata])
-                                    try self.addStorageAndWait(storage)
+                                    try storage.eraseStorageAndWait(
+                                        metadata: metadata,
+                                        soureModelHint: self.model[metadata]
+                                    )
+                                    _ = try self.addStorageAndWait(storage)
                                     
-                                    GCDQueue.Main.async {
+                                    DispatchQueue.main.async {
                                         
                                         completion(SetupResult(storage))
                                     }
@@ -244,9 +240,12 @@ public extension DataStack {
                         
                         do {
                             
-                            try self.addStorageAndWait(storage)
+                            _ = try self.addStorageAndWait(storage)
                             
-                            completion(SetupResult(storage))
+                            DispatchQueue.main.async {
+                                
+                                completion(SetupResult(storage))
+                            }
                         }
                         catch {
                             
@@ -260,16 +259,16 @@ public extension DataStack {
                     
                     do {
                         
-                        try self.addStorageAndWait(storage)
+                        _ = try self.addStorageAndWait(storage)
                         
-                        GCDQueue.Main.async {
+                        DispatchQueue.main.async {
                             
                             completion(SetupResult(storage))
                         }
                     }
                     catch {
                         
-                        GCDQueue.Main.async {
+                        DispatchQueue.main.async {
                             
                             completion(SetupResult(error))
                         }
@@ -281,9 +280,9 @@ public extension DataStack {
                 let storeError = CoreStoreError(error)
                 CoreStore.log(
                     storeError,
-                    "Failed to load SQLite \(cs_typeName(NSPersistentStore)) metadata."
+                    "Failed to load SQLite \(cs_typeName(NSPersistentStore.self)) metadata."
                 )
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
                     completion(SetupResult(storeError))
                 }
@@ -301,7 +300,7 @@ public extension DataStack {
          ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
          ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
          configuration: "Config1",
-         cloudStorageOptions: .RecreateLocalStoreOnModelMismatch
+         cloudStorageOptions: .recreateLocalStoreOnModelMismatch
      ) else {
          // iCloud is not available on the device
          return
@@ -310,48 +309,47 @@ public extension DataStack {
          storage,
          completion: { result in
              switch result {
-             case .Success(let storage): // ...
-             case .Failure(let error): // ...
+             case .success(let storage): // ...
+             case .failure(let error): // ...
              }
          }
      )
      ```
-     
      - parameter storage: the cloud storage
-     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `CloudStorage` associated to the `SetupResult.Success` may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
+     - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `SetupResult` argument indicates the result. Note that the `CloudStorage` associated to the `SetupResult.success` may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
      */
-    public func addStorage(storage: T, completion: (SetupResult) -> Void)  {
+    public func addStorage(_ storage: T, completion: @escaping (SetupResult) -> Void)  {
         
         let cacheFileURL = storage.cacheFileURL
         self.coordinator.performSynchronously {
             
             if let _ = self.persistentStoreForStorage(storage) {
                 
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
                     completion(SetupResult(storage))
                 }
                 return
             }
             
-            if let persistentStore = self.coordinator.persistentStoreForURL(cacheFileURL) {
+            if let persistentStore = self.coordinator.persistentStore(for: cacheFileURL as URL) {
                 
-                if let existingStorage = persistentStore.storageInterface as? T
-                    where storage.matchesPersistentStore(persistentStore) {
+                if let existingStorage = persistentStore.storageInterface as? T,
+                    storage.matchesPersistentStore(persistentStore) {
                     
-                    GCDQueue.Main.async {
+                    DispatchQueue.main.async {
                         
                         completion(SetupResult(existingStorage))
                     }
                     return
                 }
                 
-                let error = CoreStoreError.DifferentStorageExistsAtURL(existingPersistentStoreURL: cacheFileURL)
+                let error = CoreStoreError.differentStorageExistsAtURL(existingPersistentStoreURL: cacheFileURL)
                 CoreStore.log(
                     error,
-                    "Failed to add \(cs_typeName(storage)) at \"\(cacheFileURL)\" because a different \(cs_typeName(NSPersistentStore)) at that URL already exists."
+                    "Failed to add \(cs_typeName(storage)) at \"\(cacheFileURL)\" because a different \(cs_typeName(NSPersistentStore.self)) at that URL already exists."
                 )
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
                     completion(SetupResult(error))
                 }
@@ -361,39 +359,34 @@ public extension DataStack {
             do {
                 
                 var cloudStorageOptions = storage.cloudStorageOptions
-                cloudStorageOptions.remove(.RecreateLocalStoreOnModelMismatch)
+                cloudStorageOptions.remove(.recreateLocalStoreOnModelMismatch)
                 
-                let storeOptions = storage.storeOptionsForOptions(cloudStorageOptions)
+                let storeOptions = storage.dictionary(forOptions: cloudStorageOptions)
                 do {
                     
-                    try NSFileManager.defaultManager().createDirectoryAtURL(
-                        cacheFileURL.URLByDeletingLastPathComponent!,
-                        withIntermediateDirectories: true,
-                        attributes: nil
-                    )
-                    try self.createPersistentStoreFromStorage(
+                    _ = try self.createPersistentStoreFromStorage(
                         storage,
                         finalURL: cacheFileURL,
                         finalStoreOptions: storeOptions
                     )
-                    GCDQueue.Main.async {
+                    DispatchQueue.main.async {
                         
                         completion(SetupResult(storage))
                     }
                 }
-                catch let error as NSError where storage.cloudStorageOptions.contains(.RecreateLocalStoreOnModelMismatch) && error.isCoreDataMigrationError {
+                catch let error as NSError where storage.cloudStorageOptions.contains(.recreateLocalStoreOnModelMismatch) && error.isCoreDataMigrationError {
                     
-                    let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(
-                        storage.dynamicType.storeType,
-                        URL: cacheFileURL,
+                    let finalStoreOptions = storage.dictionary(forOptions: storage.cloudStorageOptions)
+                    let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
+                        ofType: type(of: storage).storeType,
+                        at: cacheFileURL,
                         options: storeOptions
                     )
-                    _ = try storage.eraseStorageAndWait(soureModel: self.model[metadata])
-                    
-                    try self.createPersistentStoreFromStorage(
+                    _ = try self.model[metadata].flatMap(storage.eraseStorageAndWait)
+                    _ = try self.createPersistentStoreFromStorage(
                         storage,
                         finalURL: cacheFileURL,
-                        finalStoreOptions: storeOptions
+                        finalStoreOptions: finalStoreOptions
                     )
                 }
             }
@@ -402,16 +395,16 @@ public extension DataStack {
                     
                     do {
                         
-                        try self.addStorageAndWait(storage)
+                        _ = try self.addStorageAndWait(storage)
                         
-                        GCDQueue.Main.async {
+                        DispatchQueue.main.async {
                             
                             completion(SetupResult(storage))
                         }
                     }
                     catch {
                         
-                        GCDQueue.Main.async {
+                        DispatchQueue.main.async {
                             
                             completion(SetupResult(error))
                         }
@@ -422,9 +415,9 @@ public extension DataStack {
                 let storeError = CoreStoreError(error)
                 CoreStore.log(
                     storeError,
-                    "Failed to load \(cs_typeName(NSPersistentStore)) metadata."
+                    "Failed to load \(cs_typeName(NSPersistentStore.self)) metadata."
                 )
-                GCDQueue.Main.async {
+                DispatchQueue.main.async {
                     
                     completion(SetupResult(storeError))
                 }
@@ -438,9 +431,9 @@ public extension DataStack {
      - parameter storage: the local storage
      - parameter completion: the closure to be executed on the main queue when the migration completes, either due to success or failure. The closure's `MigrationResult` argument indicates the result.
      - throws: a `CoreStoreError` value indicating the failure
-     - returns: an `NSProgress` instance if a migration has started, or `nil` is no migrations are required
+     - returns: a `Progress` instance if a migration has started, or `nil` is no migrations are required
      */
-    public func upgradeStorageIfNeeded(storage: T, completion: (MigrationResult) -> Void) throws -> NSProgress? {
+    public func upgradeStorageIfNeeded(_ storage: T, completion: @escaping (MigrationResult) -> Void) throws -> Progress? {
         
         return try self.coordinator.performSynchronously {
             
@@ -452,9 +445,9 @@ public extension DataStack {
                     "Attempted to migrate an already added \(cs_typeName(storage)) at URL \"\(fileURL)\""
                 )
                 
-                let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(
-                    storage.dynamicType.storeType,
-                    URL: fileURL,
+                let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
+                    ofType: type(of: storage).storeType,
+                    at: fileURL as URL,
                     options: storage.storeOptions
                 )
                 return self.upgradeStorageIfNeeded(
@@ -482,8 +475,7 @@ public extension DataStack {
      - throws: a `CoreStoreError` value indicating the failure
      - returns: a `MigrationType` array indicating the migration steps required for the store, or an empty array if the file does not exist yet. Otherwise, an error is thrown if either inspection of the store failed, or if no mapping model was found/inferred.
      */
-    @warn_unused_result
-    public func requiredMigrationsForStorage(storage: T) throws -> [MigrationType] {
+    public func requiredMigrationsForStorage(_ storage: T) throws -> [MigrationType] {
         
         return try self.coordinator.performSynchronously {
             
@@ -495,15 +487,15 @@ public extension DataStack {
             )
             do {
                 
-                let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(
-                    storage.dynamicType.storeType,
-                    URL: fileURL,
+                let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
+                    ofType: type(of: storage).storeType,
+                    at: fileURL as URL,
                     options: storage.storeOptions
                 )
                 
                 guard let migrationSteps = self.computeMigrationFromStorage(storage, metadata: metadata) else {
                     
-                    let error = CoreStoreError.MappingModelNotFound(
+                    let error = CoreStoreError.mappingModelNotFound(
                         localStoreURL: fileURL,
                         targetModel: self.model,
                         targetModelVersion: self.modelVersion
@@ -515,9 +507,9 @@ public extension DataStack {
                     throw error
                 }
                 
-                if migrationSteps.count > 1 && storage.localStorageOptions.contains(.PreventProgressiveMigration) {
+                if migrationSteps.count > 1 && storage.localStorageOptions.contains(.preventProgressiveMigration) {
                     
-                    let error = CoreStoreError.ProgressiveMigrationRequired(localStoreURL: fileURL)
+                    let error = CoreStoreError.progressiveMigrationRequired(localStoreURL: fileURL)
                     CoreStore.log(
                         error,
                         "Failed to find migration mapping from the \(cs_typeName(storage)) at URL \"\(fileURL)\" to version model \"\(self.modelVersion)\" without requiring progessive migrations."
@@ -547,11 +539,11 @@ public extension DataStack {
     
     // MARK: Private
     
-    private func upgradeStorageIfNeeded(storage: T, metadata: [String: AnyObject], completion: (MigrationResult) -> Void) -> NSProgress? {
+    private func upgradeStorageIfNeeded(_ storage: T, metadata: [String: Any], completion: @escaping (MigrationResult) -> Void) -> Progress? {
         
         guard let migrationSteps = self.computeMigrationFromStorage(storage, metadata: metadata) else {
             
-            let error = CoreStoreError.MappingModelNotFound(
+            let error = CoreStoreError.mappingModelNotFound(
                 localStoreURL: storage.fileURL,
                 targetModel: self.model,
                 targetModelVersion: self.modelVersion
@@ -561,7 +553,7 @@ public extension DataStack {
                 "Failed to find migration steps from \(cs_typeName(storage)) at URL \"\(storage.fileURL)\" to version model \"\(self.model)\"."
             )
             
-            GCDQueue.Main.async {
+            DispatchQueue.main.async {
                 
                 completion(MigrationResult(error))
             }
@@ -571,21 +563,21 @@ public extension DataStack {
         let numberOfMigrations: Int64 = Int64(migrationSteps.count)
         if numberOfMigrations == 0 {
             
-            GCDQueue.Main.async {
+            DispatchQueue.main.async {
                 
                 completion(MigrationResult([]))
                 return
             }
             return nil
         }
-        else if numberOfMigrations > 1 && storage.localStorageOptions.contains(.PreventProgressiveMigration) {
+        else if numberOfMigrations > 1 && storage.localStorageOptions.contains(.preventProgressiveMigration) {
             
-            let error = CoreStoreError.ProgressiveMigrationRequired(localStoreURL: storage.fileURL)
+            let error = CoreStoreError.progressiveMigrationRequired(localStoreURL: storage.fileURL)
             CoreStore.log(
                 error,
                 "Failed to find migration mapping from the \(cs_typeName(storage)) at URL \"\(storage.fileURL)\" to version model \"\(self.modelVersion)\" without requiring progessive migrations."
             )
-            GCDQueue.Main.async {
+            DispatchQueue.main.async {
                 
                 completion(MigrationResult(error))
             }
@@ -594,28 +586,28 @@ public extension DataStack {
         
         let migrationTypes = migrationSteps.map { $0.migrationType }
         var migrationResult: MigrationResult?
-        var operations = [NSOperation]()
+        var operations = [Operation]()
         var cancelled = false
         
-        let progress = NSProgress(parent: nil, userInfo: nil)
+        let progress = Progress(parent: nil, userInfo: nil)
         progress.totalUnitCount = numberOfMigrations
         
         for (sourceModel, destinationModel, mappingModel, _) in migrationSteps {
             
-            progress.becomeCurrentWithPendingUnitCount(1)
+            progress.becomeCurrent(withPendingUnitCount: 1)
             
-            let childProgress = NSProgress(parent: progress, userInfo: nil)
+            let childProgress = Progress(parent: progress, userInfo: nil)
             childProgress.totalUnitCount = 100
             
             operations.append(
-                NSBlockOperation { [weak self] in
+                BlockOperation { [weak self] in
                     
-                    guard let `self` = self where !cancelled else {
+                    guard let `self` = self, !cancelled else {
                         
                         return
                     }
                     
-                    cs_autoreleasepool {
+                    autoreleasepool {
                         
                         do {
                             
@@ -634,9 +626,9 @@ public extension DataStack {
                         }
                     }
                     
-                    GCDQueue.Main.async {
+                    DispatchQueue.main.async {
                         
-                        _ = withExtendedLifetime(childProgress) { (_: NSProgress) -> Void in }
+                        _ = withExtendedLifetime(childProgress) { (_: Progress) -> Void in }
                     }
                 }
             )
@@ -644,21 +636,12 @@ public extension DataStack {
             progress.resignCurrent()
         }
         
-        let migrationOperation = NSBlockOperation()
-        #if USE_FRAMEWORKS
-            
-            migrationOperation.qualityOfService = .Utility
-        #else
-            
-            if #available(iOS 8.0, *) {
-                
-                migrationOperation.qualityOfService = .Utility
-            }
-        #endif
+        let migrationOperation = BlockOperation()
+        migrationOperation.qualityOfService = .utility
         operations.forEach { migrationOperation.addDependency($0) }
         migrationOperation.addExecutionBlock { () -> Void in
             
-            GCDQueue.Main.async {
+            DispatchQueue.main.async {
                 
                 progress.setProgressHandler(nil)
                 completion(migrationResult ?? MigrationResult(migrationTypes))
@@ -673,10 +656,10 @@ public extension DataStack {
         return progress
     }
     
-    private func computeMigrationFromStorage(storage: T, metadata: [String: AnyObject]) -> [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]? {
+    private func computeMigrationFromStorage(_ storage: T, metadata: [String: Any]) -> [(sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, migrationType: MigrationType)]? {
         
         let model = self.model
-        if model.isConfiguration(storage.configuration, compatibleWithStoreMetadata: metadata) {
+        if model.isConfiguration(withName: storage.configuration, compatibleWithStoreMetadata: metadata) {
             
             return []
         }
@@ -695,10 +678,11 @@ public extension DataStack {
         
         while let nextVersion = migrationChain.nextVersionFrom(currentVersion),
             let sourceModel = model[currentVersion],
-            let destinationModel = model[nextVersion] where sourceModel != model {
+            sourceModel != model,
+            let destinationModel = model[nextVersion] {
                 
                 if let mappingModel = NSMappingModel(
-                    fromBundles: storage.mappingModelBundles,
+                    from: storage.mappingModelBundles,
                     forSourceModel: sourceModel,
                     destinationModel: destinationModel) {
                     
@@ -707,7 +691,7 @@ public extension DataStack {
                             sourceModel: sourceModel,
                             destinationModel: destinationModel,
                             mappingModel: mappingModel,
-                            migrationType: .Heavyweight(
+                            migrationType: .heavyweight(
                                 sourceVersion: currentVersion,
                                 destinationVersion: nextVersion
                             )
@@ -718,8 +702,8 @@ public extension DataStack {
                     
                     do {
                         
-                        let mappingModel = try NSMappingModel.inferredMappingModelForSourceModel(
-                            sourceModel,
+                        let mappingModel = try NSMappingModel.inferredMappingModel(
+                            forSourceModel: sourceModel,
                             destinationModel: destinationModel
                         )
                         
@@ -728,7 +712,7 @@ public extension DataStack {
                                 sourceModel: sourceModel,
                                 destinationModel: destinationModel,
                                 mappingModel: mappingModel,
-                                migrationType: .Lightweight(
+                                migrationType: .lightweight(
                                     sourceVersion: currentVersion,
                                     destinationVersion: nextVersion
                                 )
@@ -751,24 +735,25 @@ public extension DataStack {
         return nil
     }
     
-    private func startMigrationForStorage(storage: T, sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, progress: NSProgress) throws {
+    private func startMigrationForStorage(_ storage: T, sourceModel: NSManagedObjectModel, destinationModel: NSManagedObjectModel, mappingModel: NSMappingModel, progress: Progress) throws {
         
         let fileURL = storage.fileURL
         
-        let temporaryDirectoryURL = NSURL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
-            .URLByAppendingPathComponent(NSBundle.mainBundle().bundleIdentifier ?? "com.CoreStore.DataStack")!
-            .URLByAppendingPathComponent(NSProcessInfo().globallyUniqueString)
+        let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
+            .appendingPathComponent(Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack")
+            .appendingPathComponent(ProcessInfo().globallyUniqueString)
         
-        let fileManager = NSFileManager.defaultManager()
-        try! fileManager.createDirectoryAtURL(
-            temporaryDirectoryURL!,
+        let fileManager = FileManager.default
+        try! fileManager.createDirectory(
+            at: temporaryDirectoryURL,
             withIntermediateDirectories: true,
             attributes: nil
         )
         
-        let temporaryFileURL = temporaryDirectoryURL!.URLByAppendingPathComponent(
-            fileURL.lastPathComponent!,
-            isDirectory: false)!
+        let temporaryFileURL = temporaryDirectoryURL.appendingPathComponent(
+            fileURL.lastPathComponent,
+            isDirectory: false
+        )
         
         let migrationManager = MigrationManager(
             sourceModel: sourceModel,
@@ -778,13 +763,13 @@ public extension DataStack {
         
         do {
             
-            try migrationManager.migrateStoreFromURL(
-                fileURL,
-                type: storage.dynamicType.storeType,
+            try migrationManager.migrateStore(
+                from: fileURL,
+                sourceType: type(of: storage).storeType,
                 options: nil,
-                withMappingModel: mappingModel,
+                with: mappingModel,
                 toDestinationURL: temporaryFileURL,
-                destinationType: storage.dynamicType.storeType,
+                destinationType: type(of: storage).storeType,
                 destinationOptions: nil
             )
         }
@@ -792,7 +777,7 @@ public extension DataStack {
             
             do {
                 
-                try fileManager.removeItemAtURL(temporaryFileURL)
+                try fileManager.removeItem(at: temporaryFileURL)
             }
             catch _ { }
             
@@ -809,9 +794,9 @@ public extension DataStack {
         
         do {
             
-            try fileManager.replaceItemAtURL(
-                fileURL,
-                withItemAtURL: temporaryFileURL,
+            try fileManager.replaceItem(
+                at: fileURL as URL,
+                withItemAt: temporaryFileURL,
                 backupItemName: nil,
                 options: [],
                 resultingItemURL: nil
@@ -823,7 +808,7 @@ public extension DataStack {
             
             do {
                 
-                try fileManager.removeItemAtURL(temporaryFileURL)
+                try fileManager.removeItem(at: temporaryFileURL)
             }
             catch _ { }
             
@@ -838,159 +823,4 @@ public extension DataStack {
             throw fileError
         }
     }
-    
-    
-    // MARK: Deprecated
-    
-    /**
-     Deprecated. Use `addStorage(_:completion:)` by passing a `InMemoryStore` instance.
-     */
-    @available(*, deprecated=2.0.0, message="Use addStorage(_:completion:) by passing a InMemoryStore instance.")
-    public func addInMemoryStore(configuration configuration: String? = nil, completion: (PersistentStoreResult) -> Void) {
-        
-        self.addStorage(
-            InMemoryStore(configuration: configuration),
-            completion: { result in
-                
-                switch result {
-                    
-                case .Success(let storage):
-                    completion(PersistentStoreResult(self.persistentStoreForStorage(storage)!))
-                    
-                case .Failure(let error):
-                    completion(PersistentStoreResult(error as NSError))
-                }
-            }
-        )
-    }
-    
-    /**
-     Deprecated. Use `addStorage(_:completion:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use addStorage(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public func addSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
-        
-        return self.addStorage(
-            LegacySQLiteStore(
-                fileName: fileName,
-                configuration: configuration,
-                mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
-                localStorageOptions: resetStoreOnModelMismatch ? .RecreateStoreOnModelMismatch : .None
-            ),
-            completion: { result in
-                
-                switch result {
-                    
-                case .Success(let storage):
-                    completion(PersistentStoreResult(self.persistentStoreForStorage(storage)!))
-                    
-                case .Failure(let error):
-                    completion(PersistentStoreResult(error as NSError))
-                }
-            }
-        )
-    }
-    
-    /**
-     Deprecated. Use `addSQLiteStore(_:completion:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use addSQLiteStore(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public func addSQLiteStore(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = NSBundle.allBundles(), resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
-        
-        return self.addStorage(
-            LegacySQLiteStore(
-                fileURL: fileURL,
-                configuration: configuration,
-                mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
-                localStorageOptions: resetStoreOnModelMismatch ? .RecreateStoreOnModelMismatch : .None
-            ),
-            completion: { result in
-                
-                switch result {
-                    
-                case .Success(let storage):
-                    completion(PersistentStoreResult(self.persistentStoreForStorage(storage)!))
-                    
-                case .Failure(let error):
-                    completion(PersistentStoreResult(error as NSError))
-                }
-            }
-        )
-    }
-    
-    /**
-     Deprecated. Use `upgradeStorageIfNeeded(_:completion:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use upgradeStorageIfNeeded(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public func upgradeSQLiteStoreIfNeeded(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), completion: (MigrationResult) -> Void) throws -> NSProgress? {
-        
-        return try self.upgradeStorageIfNeeded(
-            LegacySQLiteStore(
-                fileName: fileName,
-                configuration: configuration,
-                mappingModelBundles: mappingModelBundles
-            ),
-            completion: completion
-        )
-    }
-    
-    /**
-     Deprecated. Use `upgradeStorageIfNeeded(_:completion:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use upgradeStorageIfNeeded(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public func upgradeSQLiteStoreIfNeeded(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), completion: (MigrationResult) -> Void) throws -> NSProgress? {
-        
-        return try self.upgradeStorageIfNeeded(
-            LegacySQLiteStore(
-                fileURL: fileURL,
-                configuration: configuration,
-                mappingModelBundles: mappingModelBundles
-            ),
-            completion: completion
-        )
-    }
-    
-    /**
-     Deprecated. Use `requiredMigrationsForStorage(_:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use requiredMigrationsForStorage(_:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    @warn_unused_result
-    public func requiredMigrationsForSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles() as [NSBundle]) throws -> [MigrationType] {
-        
-        return try self.requiredMigrationsForStorage(
-            LegacySQLiteStore(
-                fileName: fileName,
-                configuration: configuration,
-                mappingModelBundles: mappingModelBundles
-            )
-        )
-    }
-    
-    /**
-     Deprecated. Use `requiredMigrationsForStorage(_:)` by passing a `LegacySQLiteStore` instance.
-     
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use requiredMigrationsForStorage(_:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    @warn_unused_result
-    public func requiredMigrationsForSQLiteStore(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles() as [NSBundle]) throws -> [MigrationType] {
-        
-        return try self.requiredMigrationsForStorage(
-            LegacySQLiteStore(
-                fileURL: fileURL,
-                configuration: configuration,
-                mappingModelBundles: mappingModelBundles
-            )
-        )
-    }
 }
diff --git a/Sources/Migrating/MigrationChain.swift b/Sources/Migrating/MigrationChain.swift
index 2d5c861..9507303 100644
--- a/Sources/Migrating/MigrationChain.swift
+++ b/Sources/Migrating/MigrationChain.swift
@@ -60,7 +60,7 @@ import CoreData
  - a version appears twice as a key in a dictionary literal
  - a loop is found in any of the paths
  */
-public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, DictionaryLiteralConvertible, ArrayLiteralConvertible, Equatable {
+public struct MigrationChain: ExpressibleByNilLiteral, ExpressibleByStringLiteral, ExpressibleByDictionaryLiteral, ExpressibleByArrayLiteral, Equatable {
     
     /**
      Initializes the `MigrationChain` with empty values, which instructs the `DataStack` to use the .xcdatamodel's current version as the final version, and to disable progressive migrations.
@@ -87,9 +87,9 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
     /**
      Initializes the `MigrationChain` with a linear order of versions, which becomes the order of the `DataStack`'s progressive migrations.
      */
-    public init(_ elements: T) {
+    public init(_ elements: T) where T.Iterator.Element == String, T.SubSequence.Iterator.Element == String, T.Index: Comparable {
         
-        CoreStore.assert(Set(elements).count == Array(elements).count, "\(cs_typeName(MigrationChain))'s migration chain could not be created due to duplicate version strings.")
+        CoreStore.assert(Set(elements).count == Array(elements).count, "\(cs_typeName(MigrationChain.self))'s migration chain could not be created due to duplicate version strings.")
         
         var lastVersion: String?
         var versionTree = [String: String]()
@@ -105,8 +105,8 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
         }
         
         self.versionTree = versionTree
-        self.rootVersions = Set([elements.first].flatMap { $0 == nil ? [] : [$0!] })
-        self.leafVersions = Set([elements.last].flatMap { $0 == nil ? [] : [$0!] })
+        self.rootVersions = Set(elements.prefix(1))
+        self.leafVersions = Set(elements.suffix(1))
         self.valid = valid
     }
     
@@ -124,7 +124,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
                 return
             }
             
-            CoreStore.assert(false, "\(cs_typeName(MigrationChain))'s migration chain could not be created due to ambiguous version paths.")
+            CoreStore.assert(false, "\(cs_typeName(MigrationChain.self))'s migration chain could not be created due to ambiguous version paths.")
             
             valid = false
         }
@@ -138,11 +138,11 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
             
             var checklist: Set = [start]
             var version = start
-            while let nextVersion = versionTree[version] where nextVersion != version {
+            while let nextVersion = versionTree[version], nextVersion != version {
                 
                 if checklist.contains(nextVersion) {
                     
-                    CoreStore.assert(false, "\(cs_typeName(MigrationChain))'s migration chain could not be created due to looping version paths.")
+                    CoreStore.assert(false, "\(cs_typeName(MigrationChain.self))'s migration chain could not be created due to looping version paths.")
                     
                     return true
                 }
@@ -154,7 +154,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
         }
         
         self.versionTree = versionTree
-        self.rootVersions = Set(versionTree.keys).subtract(versionTree.values)
+        self.rootVersions = Set(versionTree.keys).subtracting(versionTree.values)
         self.leafVersions = leafVersions
         self.valid = valid && Set(versionTree.keys).union(versionTree.values).filter { isVersionAmbiguous($0) }.count <= 0
     }
@@ -168,7 +168,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
     }
     
     
-    // MARK: NilLiteralConvertible
+    // MARK: ExpressibleByNilLiteral
     
     public init(nilLiteral: ()) {
         
@@ -176,7 +176,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
     }
     
     
-    // MARK: StringLiteralConvertible
+    // MARK: ExpressibleByStringLiteral
     
     public init(stringLiteral value: String) {
         
@@ -200,7 +200,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
     }
     
     
-    // MARK: DictionaryLiteralConvertible
+    // MARK: ExpressibleByDictionaryLiteral
     
     public init(dictionaryLiteral elements: (String, String)...) {
         
@@ -208,7 +208,7 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
     }
     
     
-    // MARK: ArrayLiteralConvertible
+    // MARK: ExpressibleByArrayLiteral
     
     public init(arrayLiteral elements: String...) {
         
@@ -216,6 +216,17 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
     }
     
     
+    // MARK: Equatable
+    
+    public static func == (lhs: MigrationChain, rhs: MigrationChain) -> Bool {
+        
+        return lhs.versionTree == rhs.versionTree
+            && lhs.rootVersions == rhs.rootVersions
+            && lhs.leafVersions == rhs.leafVersions
+            && lhs.valid == rhs.valid
+    }
+    
+    
     // MARK: Internal
     
     internal let rootVersions: Set
@@ -227,16 +238,16 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
         return self.versionTree.count <= 0
     }
     
-    internal func contains(version: String) -> Bool {
+    internal func contains(_ version: String) -> Bool {
         
         return self.rootVersions.contains(version)
             || self.leafVersions.contains(version)
             || self.versionTree[version] != nil
     }
     
-    internal func nextVersionFrom(version: String) -> String? {
+    internal func nextVersionFrom(_ version: String) -> String? {
         
-        guard let nextVersion = self.versionTree[version] where nextVersion != version else {
+        guard let nextVersion = self.versionTree[version], nextVersion != version else {
             
             return nil
         }
@@ -246,18 +257,6 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
     
     // MARK: Private
     
-    private let versionTree: [String: String]
-}
-
-
-// MARK: - MigrationChain: Equatable
-
-@warn_unused_result
-public func == (lhs: MigrationChain, rhs: MigrationChain) -> Bool {
-    
-    return lhs.versionTree == rhs.versionTree
-        && lhs.rootVersions == rhs.rootVersions
-        && lhs.leafVersions == rhs.leafVersions
-        && lhs.valid == rhs.valid
+    fileprivate let versionTree: [String: String]
 }
 
diff --git a/Sources/Migrating/MigrationResult.swift b/Sources/Migrating/MigrationResult.swift
index e2c18da..a27f58d 100644
--- a/Sources/Migrating/MigrationResult.swift
+++ b/Sources/Migrating/MigrationResult.swift
@@ -49,35 +49,54 @@ import Foundation
      // ...
      let result = transaction.commit()
      switch result {
-     case .Success(let hasChanges):
+     case .success(let hasChanges):
          // hasChanges indicates if there were changes or not
-     case .Failure(let error):
+     case .failure(let error):
          // error is a CoreStoreError enum value
      }
  }
  ```
  */
-public enum MigrationResult: BooleanType, Hashable {
+public enum MigrationResult: Hashable {
     
     /**
-     `MigrationResult.Success` indicates either the migration succeeded, or there were no migrations needed. The associated value is an array of `MigrationType`s reflecting the migration steps completed.
+     `MigrationResult.success` indicates either the migration succeeded, or there were no migrations needed. The associated value is an array of `MigrationType`s reflecting the migration steps completed.
      */
-    case Success([MigrationType])
+    case success([MigrationType])
     
     /**
-     `SaveResult.Failure` indicates that the migration failed. The associated object for this value is the a `CoreStoreError` enum value.
+     `SaveResult.failure` indicates that the migration failed. The associated object for this value is the a `CoreStoreError` enum value.
      */
-    case Failure(CoreStoreError)
+    case failure(CoreStoreError)
     
     
-    // MARK: BooleanType
-    
-    public var boolValue: Bool {
+    /**
+     Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
+     */
+    public var isSuccess: Bool {
         
         switch self {
             
-        case .Success: return true
-        case .Failure: return false
+        case .success: return true
+        case .failure: return false
+        }
+    }
+    
+    
+    // MARK: Equatable
+    
+    public static func == (lhs: MigrationResult, rhs: MigrationResult) -> Bool {
+        
+        switch (lhs, rhs) {
+            
+        case (.success(let migrationTypes1), .success(let migrationTypes2)):
+            return migrationTypes1 == migrationTypes2
+            
+        case (.failure(let error1), .failure(let error2)):
+            return error1 == error2
+            
+        default:
+            return false
         }
     }
     
@@ -88,12 +107,12 @@ public enum MigrationResult: BooleanType, Hashable {
         
         switch self {
             
-        case .Success(let migrationTypes):
-            return self.boolValue.hashValue
-                ^ migrationTypes.map { $0.hashValue }.reduce(0, combine: ^).hashValue
+        case .success(let migrationTypes):
+            return true.hashValue
+                ^ migrationTypes.map { $0.hashValue }.reduce(0, ^).hashValue
             
-        case .Failure(let error):
-            return self.boolValue.hashValue ^ error.hashValue
+        case .failure(let error):
+            return false.hashValue ^ error.hashValue
         }
     }
     
@@ -102,35 +121,16 @@ public enum MigrationResult: BooleanType, Hashable {
     
     internal init(_ migrationTypes: [MigrationType]) {
         
-        self = .Success(migrationTypes)
+        self = .success(migrationTypes)
     }
     
     internal init(_ error: CoreStoreError) {
         
-        self = .Failure(error)
+        self = .failure(error)
     }
     
-    internal init(_ error: ErrorType) {
+    internal init(_ error: Error) {
         
-        self = .Failure(CoreStoreError(error))
-    }
-}
-
-
-// MARK: - SetupResult: Equatable
-
-@warn_unused_result
-public func == (lhs: MigrationResult, rhs: MigrationResult) -> Bool {
-    
-    switch (lhs, rhs) {
-        
-    case (.Success(let migrationTypes1), .Success(let migrationTypes2)):
-        return migrationTypes1 == migrationTypes2
-        
-    case (.Failure(let error1), .Failure(let error2)):
-        return error1 == error2
-        
-    default:
-        return false
+        self = .failure(CoreStoreError(error))
     }
 }
diff --git a/Sources/Migrating/MigrationType.swift b/Sources/Migrating/MigrationType.swift
index b9b3c65..f40c918 100644
--- a/Sources/Migrating/MigrationType.swift
+++ b/Sources/Migrating/MigrationType.swift
@@ -31,22 +31,22 @@ import Foundation
 /**
  The `MigrationType` specifies the type of migration required for a store.
  */
-public enum MigrationType: BooleanType, Hashable {
+public enum MigrationType: Hashable {
     
     /**
      Indicates that the persistent store matches the latest model version and no migration is needed
      */
-    case None(version: String)
+    case none(version: String)
     
     /**
      Indicates that the persistent store does not match the latest model version but Core Data can infer the mapping model, so a lightweight migration is needed
      */
-    case Lightweight(sourceVersion: String, destinationVersion: String)
+    case lightweight(sourceVersion: String, destinationVersion: String)
     
     /**
      Indicates that the persistent store does not match the latest model version and Core Data could not infer a mapping model, so a custom migration is needed
      */
-    case Heavyweight(sourceVersion: String, destinationVersion: String)
+    case heavyweight(sourceVersion: String, destinationVersion: String)
     
     /**
      Returns the source model version for the migration type. If no migration is required, `sourceVersion` will be equal to the `destinationVersion`.
@@ -55,13 +55,13 @@ public enum MigrationType: BooleanType, Hashable {
         
         switch self {
             
-        case .None(let version):
+        case .none(let version):
             return version
             
-        case .Lightweight(let sourceVersion, _):
+        case .lightweight(let sourceVersion, _):
             return sourceVersion
             
-        case .Heavyweight(let sourceVersion, _):
+        case .heavyweight(let sourceVersion, _):
             return sourceVersion
         }
     }
@@ -73,13 +73,13 @@ public enum MigrationType: BooleanType, Hashable {
         
         switch self {
             
-        case .None(let version):
+        case .none(let version):
             return version
             
-        case .Lightweight(_, let destinationVersion):
+        case .lightweight(_, let destinationVersion):
             return destinationVersion
             
-        case .Heavyweight(_, let destinationVersion):
+        case .heavyweight(_, let destinationVersion):
             return destinationVersion
         }
     }
@@ -89,7 +89,7 @@ public enum MigrationType: BooleanType, Hashable {
      */
     public var isLightweightMigration: Bool {
         
-        if case .Lightweight = self {
+        if case .lightweight = self {
             
             return true
         }
@@ -101,23 +101,44 @@ public enum MigrationType: BooleanType, Hashable {
      */
     public var isHeavyweightMigration: Bool {
         
-        if case .Heavyweight = self {
+        if case .heavyweight = self {
             
             return true
         }
         return false
     }
     
-    
-    // MARK: BooleanType
-    
-    public var boolValue: Bool {
+    /**
+     Returns `true` if the `MigrationType` is either a lightweight or a heavyweight migration. Returns `false` if no migrations specified.
+     */
+    public var hasMigration: Bool {
         
         switch self {
             
-        case .None:         return false
-        case .Lightweight:  return true
-        case .Heavyweight:  return true
+        case .none:         return false
+        case .lightweight:  return true
+        case .heavyweight:  return true
+        }
+    }
+    
+    
+    // MARK: Equatable
+    
+    public static func == (lhs: MigrationType, rhs: MigrationType) -> Bool {
+        
+        switch (lhs, rhs) {
+            
+        case (.none(let version1), .none(let version2)):
+            return version1 == version2
+            
+        case (.lightweight(let source1, let destination1), .lightweight(let source2, let destination2)):
+            return source1 == source2 && destination1 == destination2
+            
+        case (.heavyweight(let source1, let destination1), .heavyweight(let source2, let destination2)):
+            return source1 == source2 && destination1 == destination2
+            
+        default:
+            return false
         }
     }
     
@@ -126,39 +147,17 @@ public enum MigrationType: BooleanType, Hashable {
     
     public var hashValue: Int {
         
-        let preHash = self.boolValue.hashValue ^ self.isHeavyweightMigration.hashValue
+        let preHash = self.hasMigration.hashValue ^ self.isHeavyweightMigration.hashValue
         switch self {
             
-        case .None(let version):
+        case .none(let version):
             return preHash ^ version.hashValue
             
-        case .Lightweight(let sourceVersion, let destinationVersion):
+        case .lightweight(let sourceVersion, let destinationVersion):
             return preHash ^ sourceVersion.hashValue ^ destinationVersion.hashValue
             
-        case .Heavyweight(let sourceVersion, let destinationVersion):
+        case .heavyweight(let sourceVersion, let destinationVersion):
             return preHash ^ sourceVersion.hashValue ^ destinationVersion.hashValue
         }
     }
 }
-
-
-// MARK: - MigrationType: Equatable
-
-@warn_unused_result
-public func == (lhs: MigrationType, rhs: MigrationType) -> Bool {
-    
-    switch (lhs, rhs) {
-        
-    case (.None(let version1), .None(let version2)):
-        return version1 == version2
-        
-    case (.Lightweight(let source1, let destination1), .Lightweight(let source2, let destination2)):
-        return source1 == source2 && destination1 == destination2
-        
-    case (.Heavyweight(let source1, let destination1), .Heavyweight(let source2, let destination2)):
-        return source1 == source2 && destination1 == destination2
-        
-    default:
-        return false
-    }
-}
diff --git a/Sources/Migrating/SetupResult.swift b/Sources/Migrating/SetupResult.swift
index c2d7575..545412a 100644
--- a/Sources/Migrating/SetupResult.swift
+++ b/Sources/Migrating/SetupResult.swift
@@ -51,36 +51,55 @@ import CoreData
      SQLiteStore(),
      completion: { (result: SetupResult) -> Void in
          switch result {
-         case .Success(let storage):
+         case .success(let storage):
              // storage is the related StorageInterface instance
-         case .Failure(let error):
+         case .failure(let error):
              // error is the CoreStoreError enum value for the failure
          }
      }
  )
  ```
  */
-public enum SetupResult: BooleanType, Hashable {
+public enum SetupResult: Hashable {
     
     /**
-     `SetupResult.Success` indicates that the storage setup succeeded. The associated object for this `enum` value is the related `StorageInterface` instance.
+     `SetupResult.success` indicates that the storage setup succeeded. The associated object for this `enum` value is the related `StorageInterface` instance.
      */
-    case Success(T)
+    case success(T)
     
     /**
-     `SetupResult.Failure` indicates that the storage setup failed. The associated object for this value is the related `CoreStoreError` enum value.
+     `SetupResult.failure` indicates that the storage setup failed. The associated object for this value is the related `CoreStoreError` enum value.
      */
-    case Failure(CoreStoreError)
+    case failure(CoreStoreError)
     
     
-    // MARK: BooleanType
-    
-    public var boolValue: Bool {
+    /**
+     Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
+     */
+    public var isSuccess: Bool {
         
         switch self {
             
-        case .Success: return true
-        case .Failure: return false
+        case .success: return true
+        case .failure: return false
+        }
+    }
+    
+    
+    // MARK: Equatable
+    
+    public static func == (lhs: SetupResult, rhs: SetupResult) -> Bool {
+        
+        switch (lhs, rhs) {
+            
+        case (.success(let storage1), .success(let storage2)):
+            return storage1 === storage2
+            
+        case (.failure(let error1), .failure(let error2)):
+            return error1 == error2
+            
+        default:
+            return false
         }
     }
     
@@ -91,11 +110,11 @@ public enum SetupResult: BooleanType, Hashable {
         
         switch self {
             
-        case .Success(let storage):
-            return self.boolValue.hashValue ^ ObjectIdentifier(storage).hashValue
+        case .success(let storage):
+            return true.hashValue ^ ObjectIdentifier(storage).hashValue
             
-        case .Failure(let error):
-            return self.boolValue.hashValue ^ error.hashValue
+        case .failure(let error):
+            return false.hashValue ^ error.hashValue
         }
     }
     
@@ -104,80 +123,16 @@ public enum SetupResult: BooleanType, Hashable {
     
     internal init(_ storage: T) {
         
-        self = .Success(storage)
+        self = .success(storage)
     }
     
     internal init(_ error: CoreStoreError) {
         
-        self = .Failure(error)
+        self = .failure(error)
     }
     
-    internal init(_ error: ErrorType) {
+    internal init(_ error: Error) {
         
-        self = .Failure(CoreStoreError(error))
-    }
-}
-
-
-// MARK: - SetupResult: Equatable
-
-@warn_unused_result
-public func == (lhs: SetupResult, rhs: SetupResult) -> Bool {
-    
-    switch (lhs, rhs) {
-        
-    case (.Success(let storage1), .Success(let storage2)):
-        return storage1 === storage2
-        
-    case (.Failure(let error1), .Failure(let error2)):
-        return error1 == error2
-        
-    default:
-        return false
-    }
-}
-
-
-// MARK: - Deprecated
-
-/**
- Deprecated. Replaced by `SetupResult` when using the new `addStorage(_:completion:)` method variants.
- */
-@available(*, deprecated=2.0.0, message="Replaced by SetupResult by using the new addStorage(_:completion:) method variants.")
-public enum PersistentStoreResult: BooleanType {
-    
-    /**
-     Deprecated. Replaced by `SetupResult.Success` when using the new `addStorage(_:completion:)` method variants.
-     */
-    case Success(NSPersistentStore)
-    
-    /**
-     Deprecated. Replaced by `SetupResult.Failure` when using the new `addStorage(_:completion:)` method variants.
-     */
-    case Failure(NSError)
-    
-    
-    // MARK: BooleanType
-    
-    public var boolValue: Bool {
-        
-        switch self {
-            
-        case .Success: return true
-        case .Failure: return false
-        }
-    }
-    
-    
-    // MARK: Internal
-    
-    internal init(_ store: NSPersistentStore) {
-        
-        self = .Success(store)
-    }
-    
-    internal init(_ error: NSError) {
-        
-        self = .Failure(error)
+        self = .failure(CoreStoreError(error))
     }
 }
diff --git a/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift b/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift
index bcd0e8f..f8b3846 100644
--- a/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift
+++ b/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift
@@ -43,11 +43,11 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
      - parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block.
      */
     @objc
-    public func commitWithCompletion(completion: ((result: CSSaveResult) -> Void)?) {
+    public func commitWithCompletion(_ completion: ((_ result: CSSaveResult) -> Void)?) {
         
         self.bridgeToSwift.commit { (result) in
             
-            completion?(result: result.bridgeToObjectiveC)
+            completion?(result.bridgeToObjectiveC)
         }
     }
     
@@ -58,13 +58,14 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
      - returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
      */
     @objc
-    public func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
+    @discardableResult
+    public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
         
         return bridge {
             
             self.bridgeToSwift.beginSynchronous { (transaction) in
                 
-                closure(transaction: transaction.bridgeToObjectiveC)
+                closure(transaction.bridgeToObjectiveC)
             }
         }
     }
@@ -74,7 +75,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
@@ -87,7 +88,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
      - returns: a new `NSManagedObject` instance of the specified entity type.
      */
     @objc
-    public override func createInto(into: CSInto) -> AnyObject {
+    public override func createInto(_ into: CSInto) -> Any {
         
         return self.bridgeToSwift.create(into.bridgeToSwift)
     }
@@ -99,8 +100,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
      - returns: an editable proxy for the specified `NSManagedObject`.
      */
     @objc
-    @warn_unused_result
-    public override func editObject(object: NSManagedObject?) -> AnyObject? {
+    public override func editObject(_ object: NSManagedObject?) -> Any? {
         
         return self.bridgeToSwift.edit(object)
     }
@@ -113,8 +113,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
      - returns: an editable proxy for the specified `NSManagedObject`.
      */
     @objc
-    @warn_unused_result
-    public override func editInto(into: CSInto, objectID: NSManagedObjectID) -> AnyObject? {
+    public override func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
         
         return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
     }
@@ -125,7 +124,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
      - parameter object: the `NSManagedObject` type to be deleted
      */
     @objc
-    public override func deleteObject(object: NSManagedObject?) {
+    public override func deleteObject(_ object: NSManagedObject?) {
         
         self.bridgeToSwift.delete(object)
     }
@@ -136,7 +135,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
      - parameter objects: the `NSManagedObject`s type to be deleted
      */
     @objc
-    public override func deleteObjects(objects: [NSManagedObject]) {
+    public override func deleteObjects(_ objects: [NSManagedObject]) {
         
         self.bridgeToSwift.delete(objects)
     }
diff --git a/Sources/ObjectiveC/CSBaseDataTransaction+Querying.swift b/Sources/ObjectiveC/CSBaseDataTransaction+Querying.swift
index 54e467a..715dafd 100644
--- a/Sources/ObjectiveC/CSBaseDataTransaction+Querying.swift
+++ b/Sources/ObjectiveC/CSBaseDataTransaction+Querying.swift
@@ -38,17 +38,9 @@ public extension CSBaseDataTransaction {
      - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
      */
     @objc
-    @warn_unused_result
-    public func fetchExistingObject(object: NSManagedObject) -> AnyObject? {
+    public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
         
-        do {
-            
-            return try self.bridgeToSwift.context.existingObjectWithID(object.objectID)
-        }
-        catch _ {
-            
-            return nil
-        }
+        return self.bridgeToSwift.context.fetchExisting(object)
     }
     
     /**
@@ -58,17 +50,9 @@ public extension CSBaseDataTransaction {
      - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
      */
     @objc
-    @warn_unused_result
-    public func fetchExistingObjectWithID(objectID: NSManagedObjectID) -> AnyObject? {
+    public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
         
-        do {
-            
-            return try self.bridgeToSwift.context.existingObjectWithID(objectID)
-        }
-        catch _ {
-            
-            return nil
-        }
+        return self.bridgeToSwift.context.fetchExisting(objectID)
     }
     
     /**
@@ -78,10 +62,9 @@ public extension CSBaseDataTransaction {
      - returns: the `NSManagedObject` array for objects that exists in the transaction
      */
     @objc
-    @warn_unused_result
-    public func fetchExistingObjects(objects: [NSManagedObject]) -> [AnyObject] {
+    public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
         
-        return objects.flatMap { try? self.bridgeToSwift.context.existingObjectWithID($0.objectID) }
+        return self.bridgeToSwift.context.fetchExisting(objects)
     }
     
     /**
@@ -91,10 +74,9 @@ public extension CSBaseDataTransaction {
      - returns: the `NSManagedObject` array for objects that exists in the transaction
      */
     @objc
-    @warn_unused_result
-    public func fetchExistingObjectsWithIDs(objectIDs: [NSManagedObjectID]) -> [AnyObject] {
+    public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
         
-        return objectIDs.flatMap { try? self.bridgeToSwift.context.existingObjectWithID($0) }
+        return self.bridgeToSwift.context.fetchExisting(objectIDs)
     }
     
     /**
@@ -105,8 +87,7 @@ public extension CSBaseDataTransaction {
      - returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public func fetchOneFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> AnyObject? {
+    public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
         
         CoreStore.assert(
             self.bridgeToSwift.isRunningInAllowedQueue(),
@@ -123,8 +104,7 @@ public extension CSBaseDataTransaction {
      - returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public func fetchAllFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [AnyObject]? {
+    public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
         
         CoreStore.assert(
             self.bridgeToSwift.isRunningInAllowedQueue(),
@@ -141,14 +121,15 @@ public extension CSBaseDataTransaction {
      - returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public func fetchCountFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
+    public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
         
         CoreStore.assert(
             self.bridgeToSwift.isRunningInAllowedQueue(),
             "Attempted to fetch from a \(cs_typeName(self)) outside its designated queue."
         )
-        return self.bridgeToSwift.context.fetchCount(from, fetchClauses)
+        return self.bridgeToSwift.context
+            .fetchCount(from, fetchClauses)
+            .flatMap { NSNumber(value: $0) }
     }
     
     /**
@@ -159,8 +140,7 @@ public extension CSBaseDataTransaction {
      - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public func fetchObjectIDFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
+    public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
         
         CoreStore.assert(
             self.bridgeToSwift.isRunningInAllowedQueue(),
@@ -180,8 +160,7 @@ public extension CSBaseDataTransaction {
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
      */
     @objc
-    @warn_unused_result
-    public func queryValueFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> AnyObject? {
+    public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
         
         CoreStore.assert(
             self.bridgeToSwift.isRunningInAllowedQueue(),
@@ -201,8 +180,7 @@ public extension CSBaseDataTransaction {
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
      */
     @objc
-    @warn_unused_result
-    public func queryAttributesFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
+    public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
         
         CoreStore.assert(
             self.bridgeToSwift.isRunningInAllowedQueue(),
diff --git a/Sources/ObjectiveC/CSBaseDataTransaction.swift b/Sources/ObjectiveC/CSBaseDataTransaction.swift
index d86a583..b55db0e 100644
--- a/Sources/ObjectiveC/CSBaseDataTransaction.swift
+++ b/Sources/ObjectiveC/CSBaseDataTransaction.swift
@@ -55,7 +55,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: a new `NSManagedObject` instance of the specified entity type.
      */
     @objc
-    public func createInto(into: CSInto) -> AnyObject {
+    public func createInto(_ into: CSInto) -> Any {
         
         return self.bridgeToSwift.create(into.bridgeToSwift)
     }
@@ -67,8 +67,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an editable proxy for the specified `NSManagedObject`.
      */
     @objc
-    @warn_unused_result
-    public func editObject(object: NSManagedObject?) -> AnyObject? {
+    public func editObject(_ object: NSManagedObject?) -> Any? {
         
         return self.bridgeToSwift.edit(object)
     }
@@ -81,8 +80,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an editable proxy for the specified `NSManagedObject`.
      */
     @objc
-    @warn_unused_result
-    public func editInto(into: CSInto, objectID: NSManagedObjectID) -> AnyObject? {
+    public func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
         
         return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
     }
@@ -93,7 +91,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - parameter object: the `NSManagedObject` to be deleted
      */
     @objc
-    public func deleteObject(object: NSManagedObject?) {
+    public func deleteObject(_ object: NSManagedObject?) {
         
         self.bridgeToSwift.delete(object)
     }
@@ -104,7 +102,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - parameter objects: the `NSManagedObject`s to be deleted
      */
     @objc
-    public func deleteObjects(objects: [NSManagedObject]) {
+    public func deleteObjects(_ objects: [NSManagedObject]) {
         
         self.bridgeToSwift.delete(objects)
     }
@@ -127,7 +125,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObject`s that were inserted to the transaction.
      */
     @objc
-    @warn_unused_result
     public func insertedObjects() -> Set {
         
         return self.bridgeToSwift.insertedObjects()
@@ -140,8 +137,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were inserted to the transaction.
      */
     @objc
-    @warn_unused_result
-    public func insertedObjectsOfType(entity: NSManagedObject.Type) -> Set {
+    public func insertedObjectsOfType(_ entity: NSManagedObject.Type) -> Set {
         
         return self.bridgeToSwift.insertedObjects(entity)
     }
@@ -152,7 +148,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObjectID`s that were inserted to the transaction.
      */
     @objc
-    @warn_unused_result
     public func insertedObjectIDs() -> Set {
         
         return self.bridgeToSwift.insertedObjectIDs()
@@ -165,8 +160,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
      */
     @objc
-    @warn_unused_result
-    public func insertedObjectIDsOfType(entity: NSManagedObject.Type) -> Set {
+    public func insertedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set {
         
         return self.bridgeToSwift.insertedObjectIDs(entity)
     }
@@ -177,7 +171,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObject`s that were updated to the transaction.
      */
     @objc
-    @warn_unused_result
     public func updatedObjects() -> Set {
         
         return self.bridgeToSwift.updatedObjects()
@@ -190,8 +183,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were updated in the transaction.
      */
     @objc
-    @warn_unused_result
-    public func updatedObjectsOfType(entity: NSManagedObject.Type) -> Set {
+    public func updatedObjectsOfType(_ entity: NSManagedObject.Type) -> Set {
         
         return self.bridgeToSwift.updatedObjects(entity)
     }
@@ -202,7 +194,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObjectID`s that were updated in the transaction.
      */
     @objc
-    @warn_unused_result
     public func updatedObjectIDs() -> Set {
         
         return self.bridgeToSwift.updatedObjectIDs()
@@ -215,8 +206,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
      */
     @objc
-    @warn_unused_result
-    public func updatedObjectIDsOfType(entity: NSManagedObject.Type) -> Set {
+    public func updatedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set {
         
         return self.bridgeToSwift.updatedObjectIDs(entity)
     }
@@ -227,7 +217,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObject`s that were deleted from the transaction.
      */
     @objc
-    @warn_unused_result
     public func deletedObjects() -> Set {
         
         return self.bridgeToSwift.deletedObjects()
@@ -240,8 +229,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were deleted from the transaction.
      */
     @objc
-    @warn_unused_result
-    public func deletedObjectsOfType(entity: NSManagedObject.Type) -> Set {
+    public func deletedObjectsOfType(_ entity: NSManagedObject.Type) -> Set {
         
         return self.bridgeToSwift.deletedObjects(entity)
     }
@@ -253,7 +241,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
      */
     @objc
-    @warn_unused_result
     public func deletedObjectIDs() -> Set {
         
         return self.bridgeToSwift.deletedObjectIDs()
@@ -266,8 +253,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
      - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
      */
     @objc
-    @warn_unused_result
-    public func deletedObjectIDsOfType(entity: NSManagedObject.Type) -> Set {
+    public func deletedObjectIDsOfType(_ entity: NSManagedObject.Type) -> Set {
         
         return self.bridgeToSwift.deletedObjectIDs(entity)
     }
@@ -280,7 +266,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
         return ObjectIdentifier(self.bridgeToSwift).hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSBaseDataTransaction else {
             
diff --git a/Sources/ObjectiveC/CSClauseTypes.swift b/Sources/ObjectiveC/CSClauseTypes.swift
index b622687..7699912 100644
--- a/Sources/ObjectiveC/CSClauseTypes.swift
+++ b/Sources/ObjectiveC/CSClauseTypes.swift
@@ -38,7 +38,7 @@ import CoreData
 public protocol CSFetchClause {
     
     @objc
-    func applyToFetchRequest(fetchRequest: NSFetchRequest)
+    func applyToFetchRequest(_ fetchRequest: NSFetchRequest)
 }
 
 
@@ -53,7 +53,7 @@ public protocol CSFetchClause {
 public protocol CSQueryClause {
     
     @objc
-    func applyToFetchRequest(fetchRequest: NSFetchRequest)
+    func applyToFetchRequest(_ fetchRequest: NSFetchRequest)
 }
 
 
@@ -68,5 +68,5 @@ public protocol CSQueryClause {
 public protocol CSDeleteClause {
     
     @objc
-    func applyToFetchRequest(fetchRequest: NSFetchRequest)
+    func applyToFetchRequest(_ fetchRequest: NSFetchRequest)
 }
diff --git a/Sources/ObjectiveC/CSCoreStore+Migrating.swift b/Sources/ObjectiveC/CSCoreStore+Migrating.swift
index d462452..8e99891 100644
--- a/Sources/ObjectiveC/CSCoreStore+Migrating.swift
+++ b/Sources/ObjectiveC/CSCoreStore+Migrating.swift
@@ -44,11 +44,10 @@ public extension CSCoreStore {
          }
          error: &error];
      ```
-     
      - parameter storage: the `CSInMemoryStore` instance
      - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously.
      */
-    public static func addInMemoryStorage(storage: CSInMemoryStore, completion: (CSSetupResult) -> Void) {
+    public static func addInMemoryStorage(_ storage: CSInMemoryStore, completion: @escaping (CSSetupResult) -> Void) {
         
         self.defaultStack.addInMemoryStorage(storage, completion: completion)
     }
@@ -68,13 +67,12 @@ public extension CSCoreStore {
          }
          error: &error];
      ```
-     
      - parameter storage: the `CSSQLiteStore` instance
      - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously. Note that the `CSLocalStorage` associated to the `-[CSSetupResult storage]` may not always be the same instance as the parameter argument if a previous `CSLocalStorage` was already added at the same URL and with the same configuration.
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
      */
-    public static func addSQLiteStorage(storage: CSSQLiteStore, completion: (CSSetupResult) -> Void, error: NSErrorPointer) -> NSProgress? {
+    public static func addSQLiteStorage(_ storage: CSSQLiteStore, completion: @escaping (CSSetupResult) -> Void, error: NSErrorPointer) -> Progress? {
         
         return self.defaultStack.addSQLiteStorage(storage, completion: completion, error: error)
     }
@@ -88,7 +86,7 @@ public extension CSCoreStore {
      - returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
      */
     @objc
-    public static func upgradeStorageIfNeeded(storage: CSSQLiteStore, completion: (CSMigrationResult) -> Void, error: NSErrorPointer) -> NSProgress? {
+    public static func upgradeStorageIfNeeded(_ storage: CSSQLiteStore, completion: @escaping (CSMigrationResult) -> Void, error: NSErrorPointer) -> Progress? {
         
         return self.defaultStack.upgradeStorageIfNeeded(storage, completion: completion, error: error)
     }
@@ -101,8 +99,7 @@ public extension CSCoreStore {
      - returns: a `CSMigrationType` array indicating the migration steps required for the store, or an empty array if the file does not exist yet. Otherwise, `nil` is returned and the `error` argument is set if either inspection of the store failed, or if no mapping model was found/inferred.
      */
     @objc
-    @warn_unused_result
-    public static func requiredMigrationsForSQLiteStore(storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
+    public static func requiredMigrationsForSQLiteStore(_ storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
         
         return self.defaultStack.requiredMigrationsForSQLiteStore(storage, error: error)
     }
diff --git a/Sources/ObjectiveC/CSCoreStore+Observing.swift b/Sources/ObjectiveC/CSCoreStore+Observing.swift
index d0b5732..d7bcb22 100644
--- a/Sources/ObjectiveC/CSCoreStore+Observing.swift
+++ b/Sources/ObjectiveC/CSCoreStore+Observing.swift
@@ -40,8 +40,7 @@ public extension CSCoreStore {
      - returns: a `CSObjectMonitor` that monitors changes to `object`
      */
     @objc
-    @warn_unused_result
-    public static func monitorObject(object: NSManagedObject) -> CSObjectMonitor {
+    public static func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
         
         return self.defaultStack.monitorObject(object)
     }
@@ -54,8 +53,7 @@ public extension CSCoreStore {
      - returns: a `CSListMonitor` instance that monitors changes to the list
      */
     @objc
-    @warn_unused_result
-    public static func monitorListFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
+    public static func monitorListFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
         
         return self.defaultStack.monitorListFrom(from, fetchClauses: fetchClauses)
     }
@@ -68,7 +66,7 @@ public extension CSCoreStore {
      - parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
      */
     @objc
-    public static func monitorListByCreatingAsynchronously(createAsynchronously: (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause])  {
+    public static func monitorListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause])  {
         
         return self.defaultStack.monitorListByCreatingAsynchronously(
             createAsynchronously,
@@ -86,8 +84,7 @@ public extension CSCoreStore {
      - returns: a `CSListMonitor` instance that monitors changes to the list
      */
     @objc
-    @warn_unused_result
-    public static func monitorSectionedListFrom(from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
+    public static func monitorSectionedListFrom(_ from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
         
         return self.defaultStack.monitorSectionedListFrom(
             from,
@@ -105,7 +102,7 @@ public extension CSCoreStore {
      - parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
      */
     @objc
-    public static func monitorSectionedListByCreatingAsynchronously(createAsynchronously: (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
+    public static func monitorSectionedListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
         
         self.defaultStack.monitorSectionedListByCreatingAsynchronously(
             createAsynchronously,
diff --git a/Sources/ObjectiveC/CSCoreStore+Querying.swift b/Sources/ObjectiveC/CSCoreStore+Querying.swift
index b583a65..18f8864 100644
--- a/Sources/ObjectiveC/CSCoreStore+Querying.swift
+++ b/Sources/ObjectiveC/CSCoreStore+Querying.swift
@@ -38,8 +38,7 @@ public extension CSCoreStore {
      - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
      */
     @objc
-    @warn_unused_result
-    public static func fetchExistingObject(object: NSManagedObject) -> AnyObject? {
+    public static func fetchExistingObject(_ object: NSManagedObject) -> Any? {
         
         return self.defaultStack.fetchExistingObject(object)
     }
@@ -51,8 +50,7 @@ public extension CSCoreStore {
      - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
      */
     @objc
-    @warn_unused_result
-    public static func fetchExistingObjectWithID(objectID: NSManagedObjectID) -> AnyObject? {
+    public static func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
         
         return self.defaultStack.fetchExistingObjectWithID(objectID)
     }
@@ -64,8 +62,7 @@ public extension CSCoreStore {
      - returns: the `NSManagedObject` array for objects that exists in the transaction
      */
     @objc
-    @warn_unused_result
-    public static func fetchExistingObjects(objects: [NSManagedObject]) -> [AnyObject] {
+    public static func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
         
         return self.defaultStack.fetchExistingObjects(objects)
     }
@@ -77,8 +74,7 @@ public extension CSCoreStore {
      - returns: the `NSManagedObject` array for objects that exists in the transaction
      */
     @objc
-    @warn_unused_result
-    public static func fetchExistingObjectsWithIDs(objectIDs: [NSManagedObjectID]) -> [AnyObject] {
+    public static func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
         
         return self.defaultStack.fetchExistingObjectsWithIDs(objectIDs)
     }
@@ -91,8 +87,7 @@ public extension CSCoreStore {
      - returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public static func fetchOneFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> AnyObject? {
+    public static func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
         
         return self.defaultStack.fetchOneFrom(from, fetchClauses: fetchClauses)
     }
@@ -105,8 +100,7 @@ public extension CSCoreStore {
      - returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public static func fetchAllFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [AnyObject]? {
+    public static func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
         
         return self.defaultStack.fetchAllFrom(from, fetchClauses: fetchClauses)
     }
@@ -119,8 +113,7 @@ public extension CSCoreStore {
      - returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public static func fetchCountFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
+    public static func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
         
         return self.defaultStack.fetchCountFrom(from, fetchClauses: fetchClauses)
     }
@@ -133,8 +126,7 @@ public extension CSCoreStore {
      - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public static func fetchObjectIDFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
+    public static func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
         
         return self.defaultStack.fetchObjectIDFrom(from, fetchClauses: fetchClauses)
     }
@@ -147,8 +139,7 @@ public extension CSCoreStore {
      - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public static func fetchObjectIDsFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
+    public static func fetchObjectIDsFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
         
         return self.defaultStack.fetchObjectIDsFrom(from, fetchClauses: fetchClauses)
     }
@@ -164,8 +155,7 @@ public extension CSCoreStore {
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
      */
     @objc
-    @warn_unused_result
-    public static func queryValueFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> AnyObject? {
+    public static func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
         
         return self.defaultStack.queryValueFrom(from, selectClause: selectClause, queryClauses: queryClauses)
     }
@@ -181,8 +171,7 @@ public extension CSCoreStore {
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
      */
     @objc
-    @warn_unused_result
-    public static func queryAttributesFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
+    public static func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
         
         return self.defaultStack.queryAttributesFrom(from, selectClause: selectClause, queryClauses: queryClauses)
     }
diff --git a/Sources/ObjectiveC/CSCoreStore+Setup.swift b/Sources/ObjectiveC/CSCoreStore+Setup.swift
index 1550371..1fb3627 100644
--- a/Sources/ObjectiveC/CSCoreStore+Setup.swift
+++ b/Sources/ObjectiveC/CSCoreStore+Setup.swift
@@ -56,7 +56,7 @@ public extension CSCoreStore {
      - returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
      */
     @objc
-    public static func entityClassWithName(name: String) -> NSManagedObject.Type? {
+    public static func entityClassWithName(_ name: String) -> NSManagedObject.Type? {
         
         return CoreStore.entityTypesByName[name]
     }
@@ -65,9 +65,9 @@ public extension CSCoreStore {
      Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model.
      */
     @objc
-    public static func entityDescriptionForClass(type: NSManagedObject.Type) -> NSEntityDescription? {
+    public static func entityDescriptionForClass(_ type: NSManagedObject.Type) -> NSEntityDescription? {
         
-        return CoreStore.entityDescriptionForType(type)
+        return CoreStore.entityDescription(for: type)
     }
     
     /**
@@ -75,12 +75,12 @@ public extension CSCoreStore {
      ```
      CSSQLiteStore *storage = [CSCoreStore addInMemoryStorageAndWaitAndReturnError:&error];
      ```
-     
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: the `CSInMemoryStore` added to the `defaultStack`
      */
     @objc
-    public static func addInMemoryStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSInMemoryStore? {
+    @discardableResult
+    public static func addInMemoryStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSInMemoryStore? {
         
         return self.defaultStack.addInMemoryStorageAndWaitAndReturnError(error)
     }
@@ -90,12 +90,12 @@ public extension CSCoreStore {
      ```
      CSSQLiteStore *storage = [CSCoreStore addSQLiteStorageAndWaitAndReturnError:&error];
      ```
-     
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: the `CSSQLiteStore` added to the `defaultStack`
      */
     @objc
-    public static func addSQLiteStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSSQLiteStore? {
+    @discardableResult
+    public static func addSQLiteStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSSQLiteStore? {
         
         return self.defaultStack.addSQLiteStorageAndWaitAndReturnError(error)
     }
@@ -108,13 +108,13 @@ public extension CSCoreStore {
          addStorageAndWait: [[CSInMemoryStore alloc] initWithConfiguration: @"Config1"]
          error: &error];
      ```
-     
      - parameter storage: the `CSInMemoryStore`
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: the `CSInMemoryStore` added to the `defaultStack`
      */
     @objc
-    public static func addInMemoryStorageAndWait(storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
+    @discardableResult
+    public static func addInMemoryStorageAndWait(_ storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
         
         return self.defaultStack.addInMemoryStorageAndWait(storage, error: error)
     }
@@ -127,14 +127,14 @@ public extension CSCoreStore {
          addStorageAndWait: [[CSSQLiteStore alloc] initWithConfiguration: @"Config1"]
          error: &error];
      ```
-     
      - parameter storage: the `CSSQLiteStore`
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: the `CSSQLiteStore` added to the `defaultStack`
      */
     @objc
-    public static func addSQLiteStorageAndWait(storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
+    @discardableResult
+    public static func addSQLiteStorageAndWait(_ storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
         
         return self.defaultStack.addSQLiteStorageAndWait(storage, error: error)
     }
-}
\ No newline at end of file
+}
diff --git a/Sources/ObjectiveC/CSCoreStore+Transaction.swift b/Sources/ObjectiveC/CSCoreStore+Transaction.swift
index 980d509..4c2928b 100644
--- a/Sources/ObjectiveC/CSCoreStore+Transaction.swift
+++ b/Sources/ObjectiveC/CSCoreStore+Transaction.swift
@@ -36,11 +36,11 @@ public extension CSCoreStore {
      - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
      */
     @objc
-    public static func beginAsynchronous(closure: (transaction: CSAsynchronousDataTransaction) -> Void) {
+    public static func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
         
         return CoreStore.beginAsynchronous { (transaction) in
             
-            closure(transaction: transaction.bridgeToObjectiveC)
+            closure(transaction.bridgeToObjectiveC)
         }
     }
     
@@ -51,13 +51,14 @@ public extension CSCoreStore {
      - returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
      */
     @objc
-    public static func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
+    @discardableResult
+    public static func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
         
         return bridge {
             
             CoreStore.beginSynchronous { (transaction) in
                 
-                closure(transaction: transaction.bridgeToObjectiveC)
+                closure(transaction.bridgeToObjectiveC)
             }
         }
     }
@@ -69,7 +70,6 @@ public extension CSCoreStore {
      - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
      */
     @objc
-    @warn_unused_result
     public static func beginUnsafe() -> CSUnsafeDataTransaction {
         
         return bridge {
@@ -85,8 +85,7 @@ public extension CSCoreStore {
      - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
      */
     @objc
-    @warn_unused_result
-    public static func beginUnsafeWithSupportsUndo(supportsUndo: Bool) -> CSUnsafeDataTransaction {
+    public static func beginUnsafeWithSupportsUndo(_ supportsUndo: Bool) -> CSUnsafeDataTransaction {
         
         return bridge {
             
diff --git a/Sources/ObjectiveC/CSDataStack+Migrating.swift b/Sources/ObjectiveC/CSDataStack+Migrating.swift
index 5d7869c..51d4525 100644
--- a/Sources/ObjectiveC/CSDataStack+Migrating.swift
+++ b/Sources/ObjectiveC/CSDataStack+Migrating.swift
@@ -44,12 +44,11 @@ public extension CSDataStack {
          }
          error: &error];
      ```
-     
      - parameter storage: the `CSInMemoryStore` instance
      - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously.
      */
     @objc
-    public func addInMemoryStorage(storage: CSInMemoryStore, completion: (CSSetupResult) -> Void) {
+    public func addInMemoryStorage(_ storage: CSInMemoryStore, completion: @escaping (CSSetupResult) -> Void) {
         
         self.bridgeToSwift.addStorage(
             storage.bridgeToSwift,
@@ -72,14 +71,13 @@ public extension CSDataStack {
          }
          error: &error];
      ```
-     
      - parameter storage: the `CSSQLiteStore` instance
      - parameter completion: the closure to be executed on the main queue when the process completes, either due to success or failure. The closure's `CSSetupResult` argument indicates the result. This closure is NOT executed if an error is thrown, but will be executed with a failure `CSSetupResult` result if an error occurs asynchronously. Note that the `CSLocalStorage` associated to the `-[CSSetupResult storage]` may not always be the same instance as the parameter argument if a previous `CSLocalStorage` was already added at the same URL and with the same configuration.
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
      */
     @objc
-    public func addSQLiteStorage(storage: CSSQLiteStore, completion: (CSSetupResult) -> Void, error: NSErrorPointer) -> NSProgress? {
+    public func addSQLiteStorage(_ storage: CSSQLiteStore, completion: @escaping (CSSetupResult) -> Void, error: NSErrorPointer) -> Progress? {
         
         return bridge(error) {
             
@@ -99,7 +97,7 @@ public extension CSDataStack {
      - returns: an `NSProgress` instance if a migration has started. `nil` if no migrations are required or if `error` was set.
      */
     @objc
-    public func upgradeStorageIfNeeded(storage: CSSQLiteStore, completion: (CSMigrationResult) -> Void, error: NSErrorPointer) -> NSProgress? {
+    public func upgradeStorageIfNeeded(_ storage: CSSQLiteStore, completion: @escaping (CSMigrationResult) -> Void, error: NSErrorPointer) -> Progress? {
         
         return bridge(error) {
             
@@ -118,12 +116,11 @@ public extension CSDataStack {
      - returns: a `CSMigrationType` array indicating the migration steps required for the store, or an empty array if the file does not exist yet. Otherwise, `nil` is returned and the `error` argument is set if either inspection of the store failed, or if no mapping model was found/inferred.
      */
     @objc
-    @warn_unused_result
-    public func requiredMigrationsForSQLiteStore(storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
+    public func requiredMigrationsForSQLiteStore(_ storage: CSSQLiteStore, error: NSErrorPointer) -> [CSMigrationType]? {
         
         return bridge(error) {
             
             try self.bridgeToSwift.requiredMigrationsForStorage(storage.bridgeToSwift)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/Sources/ObjectiveC/CSDataStack+Observing.swift b/Sources/ObjectiveC/CSDataStack+Observing.swift
index 194fbd0..133446b 100644
--- a/Sources/ObjectiveC/CSDataStack+Observing.swift
+++ b/Sources/ObjectiveC/CSDataStack+Observing.swift
@@ -40,8 +40,7 @@ public extension CSDataStack {
      - returns: a `ObjectMonitor` that monitors changes to `object`
      */
     @objc
-    @warn_unused_result
-    public func monitorObject(object: NSManagedObject) -> CSObjectMonitor {
+    public func monitorObject(_ object: NSManagedObject) -> CSObjectMonitor {
         
         return bridge {
             
@@ -57,11 +56,10 @@ public extension CSDataStack {
      - returns: a `CSListMonitor` instance that monitors changes to the list
      */
     @objc
-    @warn_unused_result
-    public func monitorListFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
+    public func monitorListFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> CSListMonitor {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
         )
         CoreStore.assert(
@@ -74,9 +72,9 @@ public extension CSDataStack {
                 dataStack: self.bridgeToSwift,
                 from: from.bridgeToSwift,
                 sectionBy: nil,
-                applyFetchClauses: { fetchRequest in
+                applyFetchClauses: { (fetchRequest) in
                     
-                    fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
+                    fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest) }
                 }
             )
         }
@@ -90,10 +88,10 @@ public extension CSDataStack {
      - parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
      */
     @objc
-    public func monitorListByCreatingAsynchronously(createAsynchronously: (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) {
+    public func monitorListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, fetchClauses: [CSFetchClause]) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
         )
         CoreStore.assert(
@@ -104,9 +102,9 @@ public extension CSDataStack {
             dataStack: self.bridgeToSwift,
             from: from.bridgeToSwift,
             sectionBy: nil,
-            applyFetchClauses: { fetchRequest in
+            applyFetchClauses: { (fetchRequest) in
                 
-                fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
+                fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest) }
             },
             createAsynchronously: {
                 
@@ -124,11 +122,10 @@ public extension CSDataStack {
      - returns: a `CSListMonitor` instance that monitors changes to the list
      */
     @objc
-    @warn_unused_result
-    public func monitorSectionedListFrom(from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
+    public func monitorSectionedListFrom(_ from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> CSListMonitor {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
         )
         CoreStore.assert(
@@ -141,9 +138,9 @@ public extension CSDataStack {
                 dataStack: self.bridgeToSwift,
                 from: from.bridgeToSwift,
                 sectionBy: sectionBy.bridgeToSwift,
-                applyFetchClauses: { fetchRequest in
+                applyFetchClauses: { (fetchRequest) in
                     
-                    fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
+                    fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest) }
                 }
             )
         }
@@ -157,10 +154,10 @@ public extension CSDataStack {
      - parameter sectionBy: a `CSSectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
      - parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
      */
-    public func monitorSectionedListByCreatingAsynchronously(createAsynchronously: (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
+    public func monitorSectionedListByCreatingAsynchronously(_ createAsynchronously: @escaping (CSListMonitor) -> Void, from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
         )
         CoreStore.assert(
@@ -171,9 +168,9 @@ public extension CSDataStack {
             dataStack: self.bridgeToSwift,
             from: from.bridgeToSwift,
             sectionBy: sectionBy.bridgeToSwift,
-            applyFetchClauses: { fetchRequest in
+            applyFetchClauses: { (fetchRequest) in
                 
-                fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
+                fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest) }
             },
             createAsynchronously: {
                 
diff --git a/Sources/ObjectiveC/CSDataStack+Querying.swift b/Sources/ObjectiveC/CSDataStack+Querying.swift
index 11cd93c..4db3ce1 100644
--- a/Sources/ObjectiveC/CSDataStack+Querying.swift
+++ b/Sources/ObjectiveC/CSDataStack+Querying.swift
@@ -38,17 +38,9 @@ public extension CSDataStack {
      - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
      */
     @objc
-    @warn_unused_result
-    public func fetchExistingObject(object: NSManagedObject) -> AnyObject? {
+    public func fetchExistingObject(_ object: NSManagedObject) -> Any? {
         
-        do {
-            
-            return try self.bridgeToSwift.mainContext.existingObjectWithID(object.objectID)
-        }
-        catch _ {
-            
-            return nil
-        }
+        return self.bridgeToSwift.mainContext.fetchExisting(object)
     }
     
     /**
@@ -58,17 +50,9 @@ public extension CSDataStack {
      - returns: the `NSManagedObject` instance if the object exists in the transaction, or `nil` if not found.
      */
     @objc
-    @warn_unused_result
-    public func fetchExistingObjectWithID(objectID: NSManagedObjectID) -> AnyObject? {
+    public func fetchExistingObjectWithID(_ objectID: NSManagedObjectID) -> Any? {
         
-        do {
-            
-            return try self.bridgeToSwift.mainContext.existingObjectWithID(objectID)
-        }
-        catch _ {
-            
-            return nil
-        }
+        return self.bridgeToSwift.mainContext.fetchExisting(objectID)
     }
     
     /**
@@ -78,10 +62,9 @@ public extension CSDataStack {
      - returns: the `NSManagedObject` array for objects that exists in the transaction
      */
     @objc
-    @warn_unused_result
-    public func fetchExistingObjects(objects: [NSManagedObject]) -> [AnyObject] {
+    public func fetchExistingObjects(_ objects: [NSManagedObject]) -> [Any] {
         
-        return objects.flatMap { try? self.bridgeToSwift.mainContext.existingObjectWithID($0.objectID) }
+        return self.bridgeToSwift.mainContext.fetchExisting(objects)
     }
     
     /**
@@ -91,10 +74,9 @@ public extension CSDataStack {
      - returns: the `NSManagedObject` array for objects that exists in the transaction
      */
     @objc
-    @warn_unused_result
-    public func fetchExistingObjectsWithIDs(objectIDs: [NSManagedObjectID]) -> [AnyObject] {
+    public func fetchExistingObjectsWithIDs(_ objectIDs: [NSManagedObjectID]) -> [Any] {
         
-        return objectIDs.flatMap { try? self.bridgeToSwift.mainContext.existingObjectWithID($0) }
+        return self.bridgeToSwift.mainContext.fetchExisting(objectIDs)
     }
     
     /**
@@ -105,11 +87,10 @@ public extension CSDataStack {
      - returns: the first `NSManagedObject` instance that satisfies the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public func fetchOneFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> AnyObject? {
+    public func fetchOneFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> Any? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.bridgeToSwift.mainContext.fetchOne(from, fetchClauses)
@@ -123,11 +104,10 @@ public extension CSDataStack {
      - returns: all `NSManagedObject` instances that satisfy the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public func fetchAllFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [AnyObject]? {
+    public func fetchAllFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [Any]? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.bridgeToSwift.mainContext.fetchAll(from, fetchClauses)
@@ -141,14 +121,15 @@ public extension CSDataStack {
      - returns: the number `NSManagedObject`s that satisfy the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public func fetchCountFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
+    public func fetchCountFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSNumber? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
-        return self.bridgeToSwift.mainContext.fetchCount(from, fetchClauses)
+        return self.bridgeToSwift.mainContext
+            .fetchCount(from, fetchClauses)
+            .flatMap { NSNumber(value: $0) }
     }
     
     /**
@@ -159,11 +140,10 @@ public extension CSDataStack {
      - returns: the `NSManagedObjectID` for the first `NSManagedObject` that satisfies the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public func fetchObjectIDFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
+    public func fetchObjectIDFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.bridgeToSwift.mainContext.fetchObjectID(from, fetchClauses)
@@ -177,11 +157,10 @@ public extension CSDataStack {
      - returns: the `NSManagedObjectID` for all `NSManagedObject`s that satisfy the specified `CSFetchClause`s
      */
     @objc
-    @warn_unused_result
-    public func fetchObjectIDsFrom(from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
+    public func fetchObjectIDsFrom(_ from: CSFrom, fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to fetch from a \(cs_typeName(self)) outside the main thread."
         )
         return self.bridgeToSwift.mainContext.fetchObjectIDs(from, fetchClauses)
@@ -198,11 +177,10 @@ public extension CSDataStack {
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
      */
     @objc
-    @warn_unused_result
-    public func queryValueFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> AnyObject? {
+    public func queryValueFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> Any? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to query from a \(cs_typeName(self)) outside the main thread."
         )
         return self.bridgeToSwift.mainContext.queryValue(from, selectClause, queryClauses)
@@ -219,11 +197,10 @@ public extension CSDataStack {
      - returns: the result of the the query. The type of the return value is specified by the generic type of the `CSSelect` parameter.
      */
     @objc
-    @warn_unused_result
-    public func queryAttributesFrom(from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
+    public func queryAttributesFrom(_ from: CSFrom, selectClause: CSSelect, queryClauses: [CSQueryClause]) -> [[String: Any]]? {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to query from a \(cs_typeName(self)) outside the main thread."
         )
         return self.bridgeToSwift.mainContext.queryAttributes(from, selectClause, queryClauses)
diff --git a/Sources/ObjectiveC/CSDataStack+Transaction.swift b/Sources/ObjectiveC/CSDataStack+Transaction.swift
index a257825..f0d35d5 100644
--- a/Sources/ObjectiveC/CSDataStack+Transaction.swift
+++ b/Sources/ObjectiveC/CSDataStack+Transaction.swift
@@ -36,11 +36,11 @@ public extension CSDataStack {
      - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
      */
     @objc
-    public func beginAsynchronous(closure: (transaction: CSAsynchronousDataTransaction) -> Void) {
+    public func beginAsynchronous(_ closure: @escaping (_ transaction: CSAsynchronousDataTransaction) -> Void) {
         
         return self.bridgeToSwift.beginAsynchronous { (transaction) in
             
-            closure(transaction: transaction.bridgeToObjectiveC)
+            closure(transaction.bridgeToObjectiveC)
         }
     }
     
@@ -51,13 +51,14 @@ public extension CSDataStack {
      - returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
      */
     @objc
-    public func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
+    @discardableResult
+    public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
         
         return bridge {
             
             self.bridgeToSwift.beginSynchronous { (transaction) in
                 
-                closure(transaction: transaction.bridgeToObjectiveC)
+                closure(transaction.bridgeToObjectiveC)
             }
         }
     }
@@ -69,7 +70,6 @@ public extension CSDataStack {
      - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
      */
     @objc
-    @warn_unused_result
     public func beginUnsafe() -> CSUnsafeDataTransaction {
         
         return bridge {
@@ -85,8 +85,7 @@ public extension CSDataStack {
      - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
      */
     @objc
-    @warn_unused_result
-    public func beginUnsafeWithSupportsUndo(supportsUndo: Bool) -> CSUnsafeDataTransaction {
+    public func beginUnsafeWithSupportsUndo(_ supportsUndo: Bool) -> CSUnsafeDataTransaction {
         
         return bridge {
             
diff --git a/Sources/ObjectiveC/CSDataStack.swift b/Sources/ObjectiveC/CSDataStack.swift
index f416664..4965144 100644
--- a/Sources/ObjectiveC/CSDataStack.swift
+++ b/Sources/ObjectiveC/CSDataStack.swift
@@ -54,12 +54,12 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
      - parameter versionChain: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
      */
     @objc
-    public convenience init(modelName: String?, bundle: NSBundle?, versionChain: [String]?) {
+    public convenience init(modelName: String?, bundle: Bundle?, versionChain: [String]?) {
         
         self.init(
             DataStack(
                 modelName: modelName ?? DataStack.applicationName,
-                bundle: bundle ?? NSBundle.mainBundle(),
+                bundle: bundle ?? Bundle.main,
                 migrationChain: versionChain.flatMap { MigrationChain($0) } ?? nil
             )
         )
@@ -73,12 +73,12 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
      - parameter versionTree: the version strings that indicate the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
      */
     @objc
-    public convenience init(modelName: String?, bundle: NSBundle?, versionTree: [String: String]?) {
+    public convenience init(modelName: String?, bundle: Bundle?, versionTree: [String: String]?) {
         
         self.init(
             DataStack(
                 modelName: modelName ?? DataStack.applicationName,
-                bundle: bundle ?? NSBundle.mainBundle(),
+                bundle: bundle ?? Bundle.main,
                 migrationChain: versionTree.flatMap { MigrationChain($0) } ?? nil
             )
         )
@@ -142,7 +142,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSManagedObject` class for the given entity name, or `nil` if not found
      */
     @objc
-    public func entityClassWithName(name: String) -> NSManagedObject.Type? {
+    public func entityClassWithName(_ name: String) -> NSManagedObject.Type? {
         
         return self.bridgeToSwift.entityTypesByName[name]
     }
@@ -151,9 +151,9 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
      Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from stack's model.
      */
     @objc
-    public func entityDescriptionForClass(type: NSManagedObject.Type) -> NSEntityDescription? {
+    public func entityDescriptionForClass(_ type: NSManagedObject.Type) -> NSEntityDescription? {
         
-        return self.bridgeToSwift.entityDescriptionForType(type)
+        return self.bridgeToSwift.entityDescription(for: type)
     }
     
     /**
@@ -161,16 +161,16 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
      ```
      CSSQLiteStore *storage = [dataStack addInMemoryStorageAndWaitAndReturnError:&error];
      ```
-     
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: the `CSInMemoryStore` added to the stack
      */
     @objc
-    public func addInMemoryStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSInMemoryStore? {
+    @discardableResult
+    public func addInMemoryStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSInMemoryStore? {
         
         return bridge(error) {
             
-            try self.bridgeToSwift.addStorageAndWait(InMemoryStore)
+            try self.bridgeToSwift.addStorageAndWait(InMemoryStore.self)
         }
     }
     
@@ -179,16 +179,16 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
      ```
      CSSQLiteStore *storage = [dataStack addSQLiteStorageAndWaitAndReturnError:&error];
      ```
-     
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: the `CSSQLiteStore` added to the stack
      */
     @objc
-    public func addSQLiteStorageAndWaitAndReturnError(error: NSErrorPointer) -> CSSQLiteStore? {
+    @discardableResult
+    public func addSQLiteStorageAndWaitAndReturnError(_ error: NSErrorPointer) -> CSSQLiteStore? {
         
         return bridge(error) {
             
-            try self.bridgeToSwift.addStorageAndWait(SQLiteStore)
+            try self.bridgeToSwift.addStorageAndWait(SQLiteStore.self)
         }
     }
     
@@ -200,13 +200,13 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
          addStorageAndWait: [[CSInMemoryStore alloc] initWithConfiguration: @"Config1"]
          error: &error];
      ```
-     
      - parameter storage: the `CSInMemoryStore`
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: the `CSInMemoryStore` added to the stack
      */
     @objc
-    public func addInMemoryStorageAndWait(storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
+    @discardableResult
+    public func addInMemoryStorageAndWait(_ storage: CSInMemoryStore, error: NSErrorPointer) -> CSInMemoryStore? {
         
         return bridge(error) {
             
@@ -222,13 +222,13 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
          addStorageAndWait: [[CSSQLiteStore alloc] initWithConfiguration: @"Config1"]
          error: &error];
      ```
-     
      - parameter storage: the `CSSQLiteStore`
      - parameter error: the `NSError` pointer that indicates the reason in case of an failure
      - returns: the `CSSQLiteStore` added to the stack
      */
     @objc
-    public func addSQLiteStorageAndWait(storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
+    @discardableResult
+    public func addSQLiteStorageAndWait(_ storage: CSSQLiteStore, error: NSErrorPointer) -> CSSQLiteStore? {
         
         return bridge(error) {
             
@@ -244,7 +244,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
         return ObjectIdentifier(self.bridgeToSwift).hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSDataStack else {
             
@@ -255,7 +255,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSError.swift b/Sources/ObjectiveC/CSError.swift
index 4ae96f5..39c8c83 100644
--- a/Sources/ObjectiveC/CSError.swift
+++ b/Sources/ObjectiveC/CSError.swift
@@ -53,7 +53,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSError else {
             
@@ -64,7 +64,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
@@ -76,58 +76,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
             
             return swift
         }
-        
-        func createSwiftObject(error: CSError) -> CoreStoreError {
-            
-            guard error.domain == CoreStoreErrorDomain else {
-                
-                return .InternalError(NSError: self)
-            }
-            
-            guard let code = CoreStoreErrorCode(rawValue: error.code) else {
-                
-                return .Unknown
-            }
-            
-            let info = error.userInfo
-            switch code {
-                
-            case .UnknownError:
-                return .Unknown
-                
-            case .DifferentPersistentStoreExistsAtURL:
-                guard case let existingPersistentStoreURL as NSURL = info["existingPersistentStoreURL"] else {
-                    
-                    return .Unknown
-                }
-                return .DifferentStorageExistsAtURL(existingPersistentStoreURL: existingPersistentStoreURL)
-                
-            case .MappingModelNotFound:
-                guard let localStoreURL = info["localStoreURL"] as? NSURL,
-                    let targetModel = info["targetModel"] as? NSManagedObjectModel,
-                    let targetModelVersion = info["targetModelVersion"] as? String else {
-                        
-                        return .Unknown
-                }
-                return .MappingModelNotFound(localStoreURL: localStoreURL, targetModel: targetModel, targetModelVersion: targetModelVersion)
-                
-            case .ProgressiveMigrationRequired:
-                guard let localStoreURL = info["localStoreURL"] as? NSURL else {
-                    
-                    return .Unknown
-                }
-                return .ProgressiveMigrationRequired(localStoreURL: localStoreURL)
-                
-            case .InternalError:
-                guard case let NSError as NSError = info["NSError"] else {
-                    
-                    return .Unknown
-                }
-                return .InternalError(NSError: NSError)
-            }
-        }
-        
-        let swift = createSwiftObject(self)
+        let swift = CoreStoreError(_bridgedNSError: self) ?? .unknown
         self.swiftError = swift
         return swift
     }
@@ -138,43 +87,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
     public init(_ swiftValue: CoreStoreError) {
         
         self.swiftError = swiftValue
-        
-        let code: CoreStoreErrorCode
-        let info: [NSObject: AnyObject]
-        switch swiftValue {
-            
-        case .Unknown:
-            code = .UnknownError
-            info = [:]
-            
-        case .DifferentStorageExistsAtURL(let existingPersistentStoreURL):
-            code = .DifferentPersistentStoreExistsAtURL
-            info = [
-                "existingPersistentStoreURL": existingPersistentStoreURL
-            ]
-            
-        case .MappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
-            code = .MappingModelNotFound
-            info = [
-                "localStoreURL": localStoreURL,
-                "targetModel": targetModel,
-                "targetModelVersion": targetModelVersion
-            ]
-            
-        case .ProgressiveMigrationRequired(let localStoreURL):
-            code = .ProgressiveMigrationRequired
-            info = [
-                "localStoreURL": localStoreURL
-            ]
-            
-        case .InternalError(let NSError):
-            code = .InternalError
-            info = [
-                "NSError": NSError
-            ]
-        }
-        
-        super.init(domain: CoreStoreErrorDomain, code: code.rawValue, userInfo: info)
+        super.init(domain: CoreStoreError.errorDomain, code: swiftValue.errorCode, userInfo: swiftValue.errorUserInfo)
     }
     
     public required init?(coder aDecoder: NSCoder) {
@@ -203,33 +116,33 @@ public enum CSErrorCode: Int {
     /**
      A failure occured because of an unknown error.
      */
-    case UnknownError
+    case unknownError
     
     /**
      The `NSPersistentStore` could note be initialized because another store existed at the specified `NSURL`.
      */
-    case DifferentPersistentStoreExistsAtURL
+    case differentStorageExistsAtURL
     
     /**
      An `NSMappingModel` could not be found for a specific source and destination model versions.
      */
-    case MappingModelNotFound
+    case mappingModelNotFound
     
     /**
      Progressive migrations are disabled for a store, but an `NSMappingModel` could not be found for a specific source and destination model versions.
      */
-    case ProgressiveMigrationRequired
+    case progressiveMigrationRequired
     
     /**
      An internal SDK call failed with the specified "NSError" userInfo key.
      */
-    case InternalError
+    case internalError
 }
 
 
 // MARK: - CoreStoreError
 
-extension CoreStoreError: CoreStoreSwiftType {
+extension CoreStoreError: CoreStoreSwiftType, _ObjectiveCBridgeableError {
     
     // MARK: CoreStoreSwiftType
     
@@ -237,12 +150,79 @@ extension CoreStoreError: CoreStoreSwiftType {
         
         return CSError(self)
     }
+    
+    
+    // MARK: _ObjectiveCBridgeableError
+    
+    public init?(_bridgedNSError error: NSError) {
+        
+        guard error.domain == CoreStoreErrorDomain else {
+            
+            if error is CSError {
+                
+                self = .internalError(NSError: error)
+                return
+            }
+            return nil
+        }
+        
+        guard let code = CoreStoreErrorCode(rawValue: error.code) else {
+            
+            if error is CSError {
+                
+                self = .unknown
+                return
+            }
+            return nil
+        }
+        
+        let info = error.userInfo
+        switch code {
+            
+        case .unknownError:
+            self = .unknown
+            
+        case .differentStorageExistsAtURL:
+            guard case let existingPersistentStoreURL as URL = info["existingPersistentStoreURL"] else {
+                
+                self = .unknown
+                return
+            }
+            self = .differentStorageExistsAtURL(existingPersistentStoreURL: existingPersistentStoreURL)
+            
+        case .mappingModelNotFound:
+            guard let localStoreURL = info["localStoreURL"] as? URL,
+                let targetModel = info["targetModel"] as? NSManagedObjectModel,
+                let targetModelVersion = info["targetModelVersion"] as? String else {
+                    
+                    self = .unknown
+                    return
+            }
+            self = .mappingModelNotFound(localStoreURL: localStoreURL, targetModel: targetModel, targetModelVersion: targetModelVersion)
+            
+        case .progressiveMigrationRequired:
+            guard let localStoreURL = info["localStoreURL"] as? URL else {
+                
+                self = .unknown
+                return
+            }
+            self = .progressiveMigrationRequired(localStoreURL: localStoreURL)
+            
+        case .internalError:
+            guard case let NSError as NSError = info["NSError"] else {
+                
+                self = .unknown
+                return
+            }
+            self = .internalError(NSError: NSError)
+        }
+    }
 }
 
 
 // MARK: Internal
 
-internal extension ErrorType {
+internal extension Error {
     
     internal var bridgeToSwift: CoreStoreError {
         
@@ -254,11 +234,11 @@ internal extension ErrorType {
         case let error as CSError:
             return error.bridgeToSwift
             
-        case let error as NSError where self.dynamicType is NSError.Type:
-            return .InternalError(NSError: error)
+        case let error as NSError where type(of: self) is NSError.Type:
+            return .internalError(NSError: error)
             
         default:
-            return .Unknown
+            return .unknown
         }
     }
     
diff --git a/Sources/ObjectiveC/CSFrom.swift b/Sources/ObjectiveC/CSFrom.swift
index 2e22bff..71d8c6b 100644
--- a/Sources/ObjectiveC/CSFrom.swift
+++ b/Sources/ObjectiveC/CSFrom.swift
@@ -51,7 +51,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
      May contain `NSString` instances to pertain to named configurations, or `NSNull` to pertain to the default configuration
      */
     @objc
-    public var configurations: [AnyObject]? {
+    public var configurations: [Any]? {
         
         return self.bridgeToSwift.configurations?.map {
             
@@ -68,7 +68,6 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
      ```
      MyPersonEntity *people = [transaction fetchAllFrom:CSFromClass([MyPersonEntity class])];
      ```
-     
      - parameter entityClass: the `NSManagedObject` class type to be created
      */
     @objc
@@ -83,11 +82,10 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
      MyPersonEntity *people = [transaction fetchAllFrom:
         CSFromClass([MyPersonEntity class], @"Config1")];
      ```
-     
      - parameter configuration: the `NSPersistentStore` configuration name to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
      */
     @objc
-    public convenience init(entityClass: AnyClass, configuration: AnyObject) {
+    public convenience init(entityClass: AnyClass, configuration: Any) {
         
         switch configuration {
             
@@ -109,12 +107,11 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
         CSFromClass([MyPersonEntity class],
                      @[[NSNull null], @"Config1"])];
      ```
-     
      - parameter entity: the associated `NSManagedObject` entity class
      - parameter configurations: an array of the `NSPersistentStore` configuration names to associate objects from. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `[NSNull null]` to use the default configuration.
      */
     @objc
-    public convenience init(entityClass: AnyClass, configurations: [AnyObject]) {
+    public convenience init(entityClass: AnyClass, configurations: [Any]) {
         
         var arguments = [String?]()
         for configuration in configurations {
@@ -139,7 +136,7 @@ public final class CSFrom: NSObject, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSGroupBy.swift b/Sources/ObjectiveC/CSGroupBy.swift
index 4e0c615..2c1eaf0 100644
--- a/Sources/ObjectiveC/CSGroupBy.swift
+++ b/Sources/ObjectiveC/CSGroupBy.swift
@@ -76,7 +76,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSGroupBy else {
             
@@ -87,14 +87,14 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
     // MARK: CSQueryClause
     
     @objc
-    public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
+    public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) {
         
         self.bridgeToSwift.applyToFetchRequest(fetchRequest)
     }
diff --git a/Sources/ObjectiveC/CSInMemoryStore.swift b/Sources/ObjectiveC/CSInMemoryStore.swift
index a7c7dcc..2aa9e13 100644
--- a/Sources/ObjectiveC/CSInMemoryStore.swift
+++ b/Sources/ObjectiveC/CSInMemoryStore.swift
@@ -79,7 +79,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
      The options dictionary for the `NSPersistentStore`. For `CSInMemoryStore`s, this is always set to `nil`.
      */
     @objc
-    public var storeOptions: [String: AnyObject]? {
+    public var storeOptions: [AnyHashable: Any]? {
         
         return self.bridgeToSwift.storeOptions
     }
@@ -92,7 +92,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
         return ObjectIdentifier(self.bridgeToSwift).hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSInMemoryStore else {
             
@@ -103,7 +103,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreObjec
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSInto.swift b/Sources/ObjectiveC/CSInto.swift
index 1f65bd7..080ee04 100644
--- a/Sources/ObjectiveC/CSInto.swift
+++ b/Sources/ObjectiveC/CSInto.swift
@@ -62,7 +62,6 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
      MyPersonEntity *person = [transaction createInto:
         CSIntoClass([MyPersonEntity class])];
      ```
-     
      - parameter entityClass: the `NSManagedObject` class type to be created
      */
     @objc
@@ -77,7 +76,6 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
      MyPersonEntity *person = [transaction createInto:
         CSIntoClass([MyPersonEntity class])];
      ```
-     
      - parameter entityClass: the `NSManagedObject` class type to be created
      - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      */
@@ -95,7 +93,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSInto else {
             
@@ -106,7 +104,7 @@ public final class CSInto: NSObject, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSListMonitor.swift b/Sources/ObjectiveC/CSListMonitor.swift
index 9364f0e..5b9c359 100644
--- a/Sources/ObjectiveC/CSListMonitor.swift
+++ b/Sources/ObjectiveC/CSListMonitor.swift
@@ -48,7 +48,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSManagedObject` at the specified index
      */
     @objc
-    public subscript(index: Int) -> AnyObject {
+    public subscript(index: Int) -> Any {
         
         return self.bridgeToSwift[index]
     }
@@ -60,7 +60,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSManagedObject` at the specified index, or `nil` if out of bounds
      */
     @objc
-    public func objectAtSafeIndex(index: Int) -> AnyObject? {
+    public func objectAtSafeIndex(_ index: Int) -> Any? {
         
         return self.bridgeToSwift[safeIndex: index]
     }
@@ -73,12 +73,10 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSManagedObject` at the specified section and item index
      */
     @objc
-    public func objectAtSectionIndex(sectionIndex: Int, itemIndex: Int) -> AnyObject {
+    public func objectAtSectionIndex(_ sectionIndex: Int, itemIndex: Int) -> Any {
         
         return self.bridgeToSwift[sectionIndex, itemIndex]
-    }
-
-    /**
+    }    /**
      Returns the object at the given section and item index, or `nil` if out of bounds. This indexer is typically used for `CSListMonitor`s created as sectioned lists.
      
      - parameter sectionIndex: the section index for the object. Using a `sectionIndex` with an invalid range will return `nil`.
@@ -86,7 +84,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSManagedObject` at the specified section and item index, or `nil` if out of bounds
      */
     @objc
-    public func objectAtSafeSectionIndex(sectionIndex: Int, safeItemIndex itemIndex: Int) -> AnyObject? {
+    public func objectAtSafeSectionIndex(_ sectionIndex: Int, safeItemIndex itemIndex: Int) -> Any? {
         
         return self.bridgeToSwift[safeSectionIndex: sectionIndex, safeItemIndex: itemIndex]
     }
@@ -98,7 +96,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSManagedObject` at the specified index path
      */
     @objc
-    public func objectAtIndexPath(indexPath: NSIndexPath) -> AnyObject {
+    public func objectAtIndexPath(_ indexPath: IndexPath) -> Any {
         
         return self.bridgeToSwift[indexPath]
     }
@@ -110,7 +108,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSManagedObject` at the specified index path, or `nil` if out of bounds
      */
     @objc
-    public func objectAtSafeIndexPath(indexPath: NSIndexPath) -> AnyObject? {
+    public func objectAtSafeIndexPath(_ indexPath: IndexPath) -> Any? {
         
         return self.bridgeToSwift[safeIndexPath: indexPath]
     }
@@ -121,7 +119,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: `YES` if at least one object in any section exists, `NO` otherwise
      */
     @objc
-    @warn_unused_result
     public func hasObjects() -> Bool {
         
         return self.bridgeToSwift.hasObjects()
@@ -134,8 +131,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: `YES` if at least one object in the specified section exists, `NO` otherwise
      */
     @objc
-    @warn_unused_result
-    public func hasObjectsInSection(section: Int) -> Bool {
+    public func hasObjectsInSection(_ section: Int) -> Bool {
         
         return self.bridgeToSwift.hasObjectsInSection(section)
     }
@@ -146,7 +142,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: all objects in all sections
      */
     @objc
-    @warn_unused_result
     public func objectsInAllSections() -> [NSManagedObject] {
         
         return self.bridgeToSwift.objectsInAllSections()
@@ -159,8 +154,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: all objects in the specified section
      */
     @objc
-    @warn_unused_result
-    public func objectsInSection(section: Int) -> [NSManagedObject] {
+    public func objectsInSection(_ section: Int) -> [NSManagedObject] {
         
         return self.bridgeToSwift.objectsInSection(section)
     }
@@ -172,7 +166,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: all objects in the specified section, or `nil` if out of bounds
      */
     @objc
-    @warn_unused_result
     public func objectsInSafeSection(safeSectionIndex section: Int) -> [NSManagedObject]? {
         
         return self.bridgeToSwift.objectsInSection(safeSectionIndex: section)
@@ -184,7 +177,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the number of sections
      */
     @objc
-    @warn_unused_result
     public func numberOfSections() -> Int {
         
         return self.bridgeToSwift.numberOfSections()
@@ -196,7 +188,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the number of objects in all sections
      */
     @objc
-    @warn_unused_result
     public func numberOfObjects() -> Int {
         
         return self.bridgeToSwift.numberOfObjects()
@@ -209,8 +200,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the number of objects in the specified section
      */
     @objc
-    @warn_unused_result
-    public func numberOfObjectsInSection(section: Int) -> Int {
+    public func numberOfObjectsInSection(_ section: Int) -> Int {
         
         return self.bridgeToSwift.numberOfObjectsInSection(section)
     }
@@ -222,10 +212,11 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the number of objects in the specified section, or `nil` if out of bounds
      */
     @objc
-    @warn_unused_result
     public func numberOfObjectsInSafeSection(safeSectionIndex section: Int) -> NSNumber? {
         
-        return self.bridgeToSwift.numberOfObjectsInSection(safeSectionIndex: section)
+        return self.bridgeToSwift
+            .numberOfObjectsInSection(safeSectionIndex: section)
+            .flatMap { NSNumber(value: $0) }
     }
     
     /**
@@ -235,8 +226,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSFetchedResultsSectionInfo` for the specified section
      */
     @objc
-    @warn_unused_result
-    public func sectionInfoAtIndex(section: Int) -> NSFetchedResultsSectionInfo {
+    public func sectionInfoAtIndex(_ section: Int) -> NSFetchedResultsSectionInfo {
         
         return self.bridgeToSwift.sectionInfoAtIndex(section)
     }
@@ -248,7 +238,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if the section index is out of bounds.
      */
     @objc
-    @warn_unused_result
     public func sectionInfoAtSafeSectionIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? {
         
         return self.bridgeToSwift.sectionInfoAtIndex(safeSectionIndex: section)
@@ -260,7 +249,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSFetchedResultsSectionInfo`s for all sections
      */
     @objc
-    @warn_unused_result
     public func sections() -> [NSFetchedResultsSectionInfo] {
         
         return self.bridgeToSwift.sections()
@@ -274,8 +262,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the target section for the specified "Section Index" title and index.
      */
     @objc
-    @warn_unused_result
-    public func targetSectionForSectionIndexTitle(title title: String, index: Int) -> Int {
+    public func targetSectionForSectionIndexTitle(title: String, index: Int) -> Int {
         
         return self.bridgeToSwift.targetSectionForSectionIndex(title: title, index: index)
     }
@@ -286,7 +273,6 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the section index titles for all sections
      */
     @objc
-    @warn_unused_result
     public func sectionIndexTitles() -> [String] {
         
         return self.bridgeToSwift.sectionIndexTitles()
@@ -299,10 +285,11 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the index of the `NSManagedObject` if it exists in the `CSListMonitor`'s fetched objects, or `nil` if not found.
      */
     @objc
-    @warn_unused_result
-    public func indexOf(object: NSManagedObject) -> NSNumber? {
+    public func indexOf(_ object: NSManagedObject) -> NSNumber? {
         
-        return self.bridgeToSwift.indexOf(object)
+        return self.bridgeToSwift
+            .indexOf(object)
+            .flatMap { NSNumber(value: $0) }
     }
     
     /**
@@ -312,8 +299,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - returns: the `NSIndexPath` of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
      */
     @objc
-    @warn_unused_result
-    public func indexPathOf(object: NSManagedObject) -> NSIndexPath? {
+    public func indexPathOf(_ object: NSManagedObject) -> IndexPath? {
         
         return self.bridgeToSwift.indexPathOf(object)
     }
@@ -333,7 +319,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - parameter observer: a `CSListObserver` to send change notifications to
      */
     @objc
-    public func addListObserver(observer: CSListObserver) {
+    public func addListObserver(_ observer: CSListObserver) {
         
         let swift = self.bridgeToSwift
         swift.unregisterObserver(observer)
@@ -369,7 +355,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      
      - parameter observer: a `CSListObjectObserver` to send change notifications to
      */
-    public func addListObjectObserver(observer: CSListObjectObserver) {
+    public func addListObjectObserver(_ observer: CSListObjectObserver) {
         
         let swift = self.bridgeToSwift
         swift.unregisterObserver(observer)
@@ -425,7 +411,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - parameter observer: a `CSListSectionObserver` to send change notifications to
      */
     @objc
-    public func addListSectionObserver(observer: CSListSectionObserver) {
+    public func addListSectionObserver(_ observer: CSListSectionObserver) {
         
         let swift = self.bridgeToSwift
         swift.unregisterObserver(observer)
@@ -488,7 +474,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - parameter observer: a `CSListObserver` to unregister notifications to
      */
     @objc
-    public func removeListObserver(observer: CSListObserver) {
+    public func removeListObserver(_ observer: CSListObserver) {
         
         self.bridgeToSwift.unregisterObserver(observer)
     }
@@ -513,11 +499,11 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. Note that only specified clauses will be changed; unspecified clauses will use previous values.
      */
     @objc
-    public func refetch(fetchClauses: [CSFetchClause]) {
+    public func refetch(_ fetchClauses: [CSFetchClause]) {
         
         self.bridgeToSwift.refetch { (fetchRequest) in
             
-            fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
+            fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest) }
         }
     }
     
@@ -529,7 +515,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSListMonitor else {
             
@@ -540,7 +526,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSListObserver.swift b/Sources/ObjectiveC/CSListObserver.swift
index 3c5e580..a657d6f 100644
--- a/Sources/ObjectiveC/CSListObserver.swift
+++ b/Sources/ObjectiveC/CSListObserver.swift
@@ -51,7 +51,7 @@ public protocol CSListObserver: class, AnyObject {
      - parameter monitor: the `CSListMonitor` monitoring the list being observed
      */
     @objc
-    optional func listMonitorWillChange(monitor: CSListMonitor)
+    optional func listMonitorWillChange(_ monitor: CSListMonitor)
     
     /**
      Handles processing right after a change to the observed list occurs
@@ -59,7 +59,7 @@ public protocol CSListObserver: class, AnyObject {
      - parameter monitor: the `CSListMonitor` monitoring the object being observed
      */
     @objc
-    optional func listMonitorDidChange(monitor: CSListMonitor)
+    optional func listMonitorDidChange(_ monitor: CSListMonitor)
     
     /**
      This method is broadcast from within the `CSListMonitor`'s `-refetchWithFetchClauses:` method to let observers prepare for the internal `NSFetchedResultsController`'s pending change to its predicate, sort descriptors, etc. Note that the actual refetch will happen after the `NSFetchedResultsController`'s last `-controllerDidChangeContent:` notification completes.
@@ -67,7 +67,7 @@ public protocol CSListObserver: class, AnyObject {
      - parameter monitor: the `CSListMonitor` monitoring the object being observed
      */
     @objc
-    optional func listMonitorWillRefetch(monitor: CSListMonitor)
+    optional func listMonitorWillRefetch(_ monitor: CSListMonitor)
     
     /**
      After the `CSListMonitor`'s `-refetchWithFetchClauses:` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `-controllerDidChangeContent:` notification completes.
@@ -75,7 +75,7 @@ public protocol CSListObserver: class, AnyObject {
      - parameter monitor: the `CSListMonitor` monitoring the object being observed
      */
     @objc
-    optional func listMonitorDidRefetch(monitor: CSListMonitor)
+    optional func listMonitorDidRefetch(_ monitor: CSListMonitor)
 }
 
 
@@ -103,7 +103,7 @@ public protocol CSListObjectObserver: CSListObserver {
      - parameter indexPath: the new `NSIndexPath` for the inserted object
      */
     @objc
-    optional func listMonitor(monitor: CSListMonitor, didInsertObject object: AnyObject, toIndexPath indexPath: NSIndexPath)
+    optional func listMonitor(_ monitor: CSListMonitor, didInsertObject object: Any, toIndexPath indexPath: IndexPath)
     
     /**
      Notifies that an object was deleted from the specified `NSIndexPath` in the list
@@ -113,7 +113,7 @@ public protocol CSListObjectObserver: CSListObserver {
      - parameter indexPath: the `NSIndexPath` for the deleted object
      */
     @objc
-    optional func listMonitor(monitor: CSListMonitor, didDeleteObject object: AnyObject, fromIndexPath indexPath: NSIndexPath)
+    optional func listMonitor(_ monitor: CSListMonitor, didDeleteObject object: Any, fromIndexPath indexPath: IndexPath)
     
     /**
      Notifies that an object at the specified `NSIndexPath` was updated
@@ -123,7 +123,7 @@ public protocol CSListObjectObserver: CSListObserver {
      - parameter indexPath: the `NSIndexPath` for the updated object
      */
     @objc
-    optional func listMonitor(monitor: CSListMonitor, didUpdateObject object: AnyObject, atIndexPath indexPath: NSIndexPath)
+    optional func listMonitor(_ monitor: CSListMonitor, didUpdateObject object: Any, atIndexPath indexPath: IndexPath)
     
     /**
      Notifies that an object's index changed
@@ -134,7 +134,7 @@ public protocol CSListObjectObserver: CSListObserver {
      - parameter toIndexPath: the new `NSIndexPath` for the moved object
      */
     @objc
-    optional func listMonitor(monitor: CSListMonitor, didMoveObject object: AnyObject, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
+    optional func listMonitor(_ monitor: CSListMonitor, didMoveObject object: Any, fromIndexPath: IndexPath, toIndexPath: IndexPath)
 }
 
 
@@ -163,7 +163,7 @@ public protocol CSListSectionObserver: CSListObjectObserver {
      - parameter sectionIndex: the new section index for the new section
      */
     @objc
-    optional func listMonitor(monitor: CSListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
+    optional func listMonitor(_ monitor: CSListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
     
     /**
      Notifies that a section was inserted at the specified index
@@ -173,7 +173,7 @@ public protocol CSListSectionObserver: CSListObjectObserver {
      - parameter sectionIndex: the previous section index for the deleted section
      */
     @objc
-    optional func listMonitor(monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
+    optional func listMonitor(_ monitor: CSListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
 }
 
 #endif
diff --git a/Sources/ObjectiveC/CSMigrationResult.swift b/Sources/ObjectiveC/CSMigrationResult.swift
index 2fe7a36..56fac06 100644
--- a/Sources/ObjectiveC/CSMigrationResult.swift
+++ b/Sources/ObjectiveC/CSMigrationResult.swift
@@ -43,7 +43,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
     @objc
     public var isSuccess: Bool {
         
-        return self.bridgeToSwift.boolValue
+        return self.bridgeToSwift.isSuccess
     }
     
     /**
@@ -52,7 +52,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
     @objc
     public var isFailure: Bool {
         
-        return !self.bridgeToSwift.boolValue
+        return !self.bridgeToSwift.isSuccess
     }
     
     /**
@@ -61,7 +61,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
     @objc
     public var migrationTypes: [CSMigrationType]? {
         
-        guard case .Success(let migrationTypes) = self.bridgeToSwift else {
+        guard case .success(let migrationTypes) = self.bridgeToSwift else {
             
             return nil
         }
@@ -74,7 +74,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
     @objc
     public var error: NSError? {
         
-        guard case .Failure(let error) = self.bridgeToSwift else {
+        guard case .failure(let error) = self.bridgeToSwift else {
             
             return nil
         }
@@ -90,15 +90,15 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
      - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
      */
     @objc
-    public func handleSuccess(@noescape success: (migrationTypes: [CSMigrationType]) -> Void, @noescape failure: (error: NSError) -> Void) {
+    public func handleSuccess(_ success: (_ migrationTypes: [CSMigrationType]) -> Void, failure: (_ error: NSError) -> Void) {
         
         switch self.bridgeToSwift {
             
-        case .Success(let migrationTypes):
-            success(migrationTypes: migrationTypes.map { $0.bridgeToObjectiveC })
+        case .success(let migrationTypes):
+            success(migrationTypes.map { $0.bridgeToObjectiveC })
             
-        case .Failure(let error):
-            failure(error: error.bridgeToObjectiveC)
+        case .failure(let error):
+            failure(error.bridgeToObjectiveC)
         }
     }
     
@@ -110,13 +110,13 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
      - parameter success: the block to execute on success. The block passes an array of `CSMigrationType`s that indicates the migration steps completed.
      */
     @objc
-    public func handleSuccess(@noescape success: (migrationTypes: [CSMigrationType]) -> Void) {
+    public func handleSuccess(_ success: (_ migrationTypes: [CSMigrationType]) -> Void) {
         
-        guard case .Success(let migrationTypes) = self.bridgeToSwift else {
+        guard case .success(let migrationTypes) = self.bridgeToSwift else {
             
             return
         }
-        success(migrationTypes: migrationTypes.map { $0.bridgeToObjectiveC })
+        success(migrationTypes.map { $0.bridgeToObjectiveC })
     }
     
     /**
@@ -127,13 +127,13 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
      - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
      */
     @objc
-    public func handleFailure(@noescape failure: (error: NSError) -> Void) {
+    public func handleFailure(_ failure: (_ error: NSError) -> Void) {
         
-        guard case .Failure(let error) = self.bridgeToSwift else {
+        guard case .failure(let error) = self.bridgeToSwift else {
             
             return
         }
-        failure(error: error.bridgeToObjectiveC)
+        failure(error.bridgeToObjectiveC)
     }
     
     
@@ -144,7 +144,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSMigrationResult else {
             
@@ -155,7 +155,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSMigrationType.swift b/Sources/ObjectiveC/CSMigrationType.swift
index 5d9afe8..385adbf 100644
--- a/Sources/ObjectiveC/CSMigrationType.swift
+++ b/Sources/ObjectiveC/CSMigrationType.swift
@@ -43,7 +43,7 @@ public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
     @objc
     public var needsMigration: Bool {
         
-        return self.bridgeToSwift.boolValue
+        return self.bridgeToSwift.hasMigration
     }
     
     /**
@@ -90,7 +90,7 @@ public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSMigrationType else {
             
@@ -101,7 +101,7 @@ public final class CSMigrationType: NSObject, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSObjectMonitor.swift b/Sources/ObjectiveC/CSObjectMonitor.swift
index f55b6e8..0625fee 100644
--- a/Sources/ObjectiveC/CSObjectMonitor.swift
+++ b/Sources/ObjectiveC/CSObjectMonitor.swift
@@ -42,7 +42,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
     /**
      Returns the `NSManagedObject` instance being observed, or `nil` if the object was already deleted.
      */
-    public var object: AnyObject? {
+    public var object: Any? {
         
         return self.bridgeToSwift.object
     }
@@ -66,7 +66,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
      
      - parameter observer: an `CSObjectObserver` to send change notifications to
      */
-    public func addObjectObserver(observer: CSObjectObserver) {
+    public func addObjectObserver(_ observer: CSObjectObserver) {
         
         let swift = self.bridgeToSwift
         swift.unregisterObserver(observer)
@@ -94,7 +94,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
      
      - parameter observer: an `CSObjectObserver` to unregister notifications to
      */
-    public func removeObjectObserver(observer: CSObjectObserver) {
+    public func removeObjectObserver(_ observer: CSObjectObserver) {
         
         self.bridgeToSwift.unregisterObserver(observer)
     }
@@ -107,7 +107,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSObjectMonitor else {
             
@@ -118,7 +118,7 @@ public final class CSObjectMonitor: NSObject, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSObjectObserver.swift b/Sources/ObjectiveC/CSObjectObserver.swift
index af0f73d..7bc0934 100644
--- a/Sources/ObjectiveC/CSObjectObserver.swift
+++ b/Sources/ObjectiveC/CSObjectObserver.swift
@@ -50,7 +50,7 @@ public protocol CSObjectObserver: class, AnyObject {
      - parameter object: the `NSManagedObject` instance being observed
      */
     @objc
-    optional func objectMonitor(monitor: CSObjectMonitor, willUpdateObject object: AnyObject)
+    optional func objectMonitor(_ monitor: CSObjectMonitor, willUpdateObject object: Any)
     
     /**
      Handles processing right after a change to the observed `object` occurs
@@ -60,7 +60,7 @@ public protocol CSObjectObserver: class, AnyObject {
      - parameter changedPersistentKeys: an `NSSet` of key paths for the attributes that were changed. Note that `changedPersistentKeys` only contains keys for attributes/relationships present in the persistent store, thus transient properties will not be reported.
      */
     @objc
-    optional func objectMonitor(monitor: CSObjectMonitor, didUpdateObject object: AnyObject, changedPersistentKeys: Set)
+    optional func objectMonitor(_ monitor: CSObjectMonitor, didUpdateObject object: Any, changedPersistentKeys: Set)
     
     /**
      Handles processing right after `object` is deleted
@@ -69,7 +69,7 @@ public protocol CSObjectObserver: class, AnyObject {
      - parameter object: the `NSManagedObject` instance being observed
      */
     @objc
-    optional func objectMonitor(monitor: CSObjectMonitor, didDeleteObject object: AnyObject)
+    optional func objectMonitor(_ monitor: CSObjectMonitor, didDeleteObject object: Any)
 }
 
 #endif
diff --git a/Sources/ObjectiveC/CSOrderBy.swift b/Sources/ObjectiveC/CSOrderBy.swift
index 9be4fbc..53c97a9 100644
--- a/Sources/ObjectiveC/CSOrderBy.swift
+++ b/Sources/ObjectiveC/CSOrderBy.swift
@@ -53,7 +53,6 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
         fetchAllFrom:CSFromClass([MyPersonEntity class])
         fetchClauses:@[CSOrderByKey(CSSortAscending(@"fullname"))]]];
      ```
-     
      - parameter sortDescriptor: a `NSSortDescriptor`
      */
     @objc
@@ -69,7 +68,6 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
         fetchAllFrom:CSFromClass([MyPersonEntity class])
         fetchClauses:@[CSOrderByKeys(CSSortAscending(@"fullname"), CSSortDescending(@"age"), nil))]]];
      ```
-     
      - parameter sortDescriptors: an array of `NSSortDescriptor`s
      */
     @objc
@@ -86,7 +84,7 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSOrderBy else {
             
@@ -97,14 +95,14 @@ public final class CSOrderBy: NSObject, CSFetchClause, CSQueryClause, CSDeleteCl
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
     // MARK: CSFetchClause, CSQueryClause, CSDeleteClause
     
     @objc
-    public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
+    public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) {
         
         self.bridgeToSwift.applyToFetchRequest(fetchRequest)
     }
diff --git a/Sources/ObjectiveC/CSSQliteStore.swift b/Sources/ObjectiveC/CSSQliteStore.swift
index 0170026..f449c76 100644
--- a/Sources/ObjectiveC/CSSQliteStore.swift
+++ b/Sources/ObjectiveC/CSSQliteStore.swift
@@ -46,13 +46,13 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
      - parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
      */
     @objc
-    public convenience init(fileURL: NSURL, configuration: String?, mappingModelBundles: [NSBundle]?, localStorageOptions: Int) {
+    public convenience init(fileURL: URL, configuration: String?, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
         
         self.init(
             SQLiteStore(
                 fileURL: fileURL,
                 configuration: configuration,
-                mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
+                mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
                 localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
             )
         )
@@ -68,13 +68,13 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
      - parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
      */
     @objc
-    public convenience init(fileName: String, configuration: String?, mappingModelBundles: [NSBundle]?, localStorageOptions: Int) {
+    public convenience init(fileName: String, configuration: String?, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
         
         self.init(
             SQLiteStore(
                 fileName: fileName,
                 configuration: configuration,
-                mappingModelBundles: mappingModelBundles ?? NSBundle.allBundles(),
+                mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
                 localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
             )
         )
@@ -98,16 +98,16 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
      The `NSURL` that points to the SQLite file
      */
     @objc
-    public var fileURL: NSURL {
+    public var fileURL: URL {
      
-        return self.bridgeToSwift.fileURL
+        return self.bridgeToSwift.fileURL as URL
     }
     
     /**
      The `NSBundle`s from which to search mapping models for migrations
      */
     @objc
-    public var mappingModelBundles: [NSBundle] {
+    public var mappingModelBundles: [Bundle] {
         
         return self.bridgeToSwift.mappingModelBundles
     }
@@ -145,7 +145,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
      ```
      */
     @objc
-    public var storeOptions: [String: AnyObject]? {
+    public var storeOptions: [AnyHashable: Any]? {
         
         return self.bridgeToSwift.storeOptions
     }
@@ -154,11 +154,11 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
      Called by the `CSDataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `CSSQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
      */
     @objc
-    public func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel?, error: NSErrorPointer) -> Bool {
+    public func eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool {
         
         return bridge(error) {
             
-            try self.bridgeToSwift.eraseStorageAndWait(soureModel: soureModel)
+            try self.bridgeToSwift.eraseStorageAndWait(metadata: metadata as! [String: Any], soureModelHint: soureModelHint)
         }
     }
     
@@ -170,7 +170,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
         return ObjectIdentifier(self.bridgeToSwift).hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSSQLiteStore else {
             
@@ -181,7 +181,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSSaveResult.swift b/Sources/ObjectiveC/CSSaveResult.swift
index 3337d65..863e5bd 100644
--- a/Sources/ObjectiveC/CSSaveResult.swift
+++ b/Sources/ObjectiveC/CSSaveResult.swift
@@ -61,7 +61,7 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
     @objc
     public var hasChanges: Bool {
         
-        guard case .Success(let hasChanges) = self.bridgeToSwift else {
+        guard case .success(let hasChanges) = self.bridgeToSwift else {
             
             return false
         }
@@ -74,7 +74,7 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
     @objc
     public var error: NSError? {
         
-        guard case .Failure(let error) = self.bridgeToSwift else {
+        guard case .failure(let error) = self.bridgeToSwift else {
             
             return nil
         }
@@ -90,15 +90,15 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
      - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
      */
     @objc
-    public func handleSuccess(@noescape success: (hasChanges: Bool) -> Void, @noescape failure: (error: NSError) -> Void) {
+    public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void, failure: (_ error: NSError) -> Void) {
         
         switch self.bridgeToSwift {
             
-        case .Success(let hasChanges):
-            success(hasChanges: hasChanges)
+        case .success(let hasChanges):
+            success(hasChanges)
             
-        case .Failure(let error):
-            failure(error: error.bridgeToObjectiveC)
+        case .failure(let error):
+            failure(error.bridgeToObjectiveC)
         }
     }
     
@@ -110,13 +110,13 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
      - parameter success: the block to execute on success. The block passes a `BOOL` argument that indicates if there were any changes made.
      */
     @objc
-    public func handleSuccess(@noescape success: (hasChanges: Bool) -> Void) {
+    public func handleSuccess(_ success: (_ hasChanges: Bool) -> Void) {
         
-        guard case .Success(let hasChanges) = self.bridgeToSwift else {
+        guard case .success(let hasChanges) = self.bridgeToSwift else {
             
             return
         }
-        success(hasChanges: hasChanges)
+        success(hasChanges)
     }
     
     /**
@@ -127,13 +127,13 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
      - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
      */
     @objc
-    public func handleFailure(@noescape failure: (error: NSError) -> Void) {
+    public func handleFailure(_ failure: (_ error: NSError) -> Void) {
         
-        guard case .Failure(let error) = self.bridgeToSwift else {
+        guard case .failure(let error) = self.bridgeToSwift else {
                 
             return
         }
-        failure(error: error.bridgeToObjectiveC)
+        failure(error.bridgeToObjectiveC)
     }
     
     
@@ -144,7 +144,7 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSSaveResult else {
             
@@ -155,7 +155,7 @@ public final class CSSaveResult: NSObject, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSSectionBy.swift b/Sources/ObjectiveC/CSSectionBy.swift
index bf758f6..5a77951 100644
--- a/Sources/ObjectiveC/CSSectionBy.swift
+++ b/Sources/ObjectiveC/CSSectionBy.swift
@@ -46,7 +46,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
      - returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
      */
     @objc
-    public static func keyPath(sectionKeyPath: KeyPath) -> CSSectionBy {
+    public static func keyPath(_ sectionKeyPath: KeyPath) -> CSSectionBy {
         
         return self.init(SectionBy(sectionKeyPath))
     }
@@ -59,7 +59,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
      - returns: a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
      */
     @objc
-    public static func keyPath(sectionKeyPath: KeyPath, sectionIndexTransformer: (sectionName: String?) -> String?) -> CSSectionBy {
+    public static func keyPath(_ sectionKeyPath: KeyPath, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy {
         
         return self.init(SectionBy(sectionKeyPath, sectionIndexTransformer))
     }
@@ -69,7 +69,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSSelect.swift b/Sources/ObjectiveC/CSSelect.swift
index 65e0c21..3311019 100644
--- a/Sources/ObjectiveC/CSSelect.swift
+++ b/Sources/ObjectiveC/CSSelect.swift
@@ -45,13 +45,12 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
          select:CSSelectString(CSAttribute(@"fullname"))
          fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]];
      ```
-     
      - parameter keyPath: the attribute name
      */
     @objc
     public convenience init(keyPath: KeyPath) {
 
-        self.init(.Attribute(keyPath))
+        self.init(.attribute(keyPath))
     }
 
     /**
@@ -61,15 +60,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
          queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
          select:[CSSelect numberForTerm:[CSSelectTerm average:@"age" as:nil]]];
      ```
-     
      - parameter keyPath: the attribute name
      - parameter `as`: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "average()" is used
      - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the average value of an attribute
      */
     @objc
-    public static func average(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm {
+    public static func average(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
         
-        return self.init(.Average(keyPath, As: alias))
+        return self.init(.average(keyPath, as: alias))
     }
 
     /**
@@ -79,15 +77,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
          queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
          select:[CSSelect numberForTerm:[CSSelectTerm count:@"employeeID" as:nil]]];
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "count()" is used
      - returns: a `SelectTerm` to a `Select` clause for a count query
      */
     @objc
-    public static func count(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm {
+    public static func count(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
         
-        return self.init(.Count(keyPath, As: alias))
+        return self.init(.count(keyPath, as: alias))
     }
 
     /**
@@ -97,15 +94,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
          queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
          select:[CSSelect numberForTerm:[CSSelectTerm maximum:@"age" as:nil]]];
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "max()" is used
      - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the maximum value for an attribute
      */
     @objc
-    public static func maximum(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm {
+    public static func maximum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
         
-        return self.init(.Maximum(keyPath, As: alias))
+        return self.init(.maximum(keyPath, as: alias))
     }
 
     /**
@@ -115,15 +111,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
          queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
          select:[CSSelect numberForTerm:[CSSelectTerm minimum:@"age" as:nil]]];
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "min()" is used
      - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the minimum value for an attribute
      */
     @objc
-    public static func minimum(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm {
+    public static func minimum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
         
-        return self.init(.Minimum(keyPath, As: alias))
+        return self.init(.minimum(keyPath, as: alias))
     }
 
     /**
@@ -133,15 +128,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
          queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
          select:[CSSelect numberForTerm:[CSSelectTerm sum:@"age" as:nil]]];
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "sum()" is used
      - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the sum value for an attribute
      */
     @objc
-    public static func sum(keyPath: KeyPath, `as` alias: KeyPath?) -> CSSelectTerm {
+    public static func sum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm {
         
-        return self.init(.Sum(keyPath, As: alias))
+        return self.init(.sum(keyPath, as: alias))
     }
     
     /**
@@ -152,15 +146,14 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
          select:[CSSelect objectIDForTerm:[CSSelectTerm objectIDAs:nil]]
          fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]];
      ```
-     
      - parameter keyPath: the attribute name
      - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "objecID" is used
      - returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute
      */
     @objc
-    public static func objectIDAs(alias: KeyPath? = nil) -> CSSelectTerm {
+    public static func objectIDAs(_ alias: KeyPath? = nil) -> CSSelectTerm {
         
-        return self.init(.ObjectID(As: alias))
+        return self.init(.objectID(as: alias))
     }
 
     
@@ -171,7 +164,7 @@ public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType {
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSSelectTerm else {
             
@@ -221,7 +214,6 @@ public final class CSSelect: NSObject {
         select:CSSelectNumber(CSAggregateMax(@"age"))
         // ...
      ```
-     
      - parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
      */
     public convenience init(numberTerm: CSSelectTerm) {
@@ -237,7 +229,6 @@ public final class CSSelect: NSObject {
         select:CSSelectDecimal(CSAggregateAverage(@"price"))
         // ...
      ```
-     
      - parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
      */
     public convenience init(decimalTerm: CSSelectTerm) {
@@ -253,7 +244,6 @@ public final class CSSelect: NSObject {
         select:CSSelectString(CSAttribute(@"fullname"))
         // ...
      ```
-     
      - parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
      */
     public convenience init(stringTerm: CSSelectTerm) {
@@ -269,12 +259,11 @@ public final class CSSelect: NSObject {
         select:CSSelectDate(CSAggregateMax(@"updatedDate"))
         // ...
      ```
-     
      - parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
      */
     public convenience init(dateTerm: CSSelectTerm) {
         
-        self.init(Select(dateTerm.bridgeToSwift))
+        self.init(Select(dateTerm.bridgeToSwift))
     }
     
     /**
@@ -285,12 +274,11 @@ public final class CSSelect: NSObject {
         select:CSSelectData(CSAttribute(@"imageData"))
         // ...
      ```
-     
      - parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
      */
     public convenience init(dataTerm: CSSelectTerm) {
         
-        self.init(Select(dataTerm.bridgeToSwift))
+        self.init(Select(dataTerm.bridgeToSwift))
     }
     
     /**
@@ -301,12 +289,11 @@ public final class CSSelect: NSObject {
         select:CSSelectObjectID()
         // ...
      ```
-     
      - parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
      */
     public convenience init(objectIDTerm: ()) {
         
-        self.init(Select(.ObjectID()))
+        self.init(Select(.objectID()))
     }
     
     /**
@@ -316,11 +303,10 @@ public final class CSSelect: NSObject {
          queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]]
          select:[CSSelect dictionaryForTerm:[CSSelectTerm maximum:@"age" as:nil]]];
      ```
-     
      - parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query
      - returns: a `CSSelect` clause for querying an entity attribute
      */
-    public static func dictionaryForTerm(term: CSSelectTerm) -> CSSelect {
+    public static func dictionaryForTerm(_ term: CSSelectTerm) -> CSSelect {
         
         return self.init(Select(term.bridgeToSwift))
     }
@@ -335,11 +321,10 @@ public final class CSSelect: NSObject {
              [CSSelectTerm attribute:@"age" as:nil]
          ]]];
      ```
-     
      - parameter terms: the `CSSelectTerm`s specifying the attribute/aggregate values to query
      - returns: a `CSSelect` clause for querying an entity attribute
      */
-    public static func dictionaryForTerms(terms: [CSSelectTerm]) -> CSSelect {
+    public static func dictionaryForTerms(_ terms: [CSSelectTerm]) -> CSSelect {
         
         return self.init(Select(terms.map { $0.bridgeToSwift }))
     }
@@ -350,10 +335,10 @@ public final class CSSelect: NSObject {
     public override var hash: Int {
         
         return self.attributeType.hashValue
-            ^ self.selectTerms.map { $0.hashValue }.reduce(0, combine: ^)
+            ^ self.selectTerms.map { $0.hashValue }.reduce(0, ^)
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSSelect else {
             
@@ -365,7 +350,7 @@ public final class CSSelect: NSObject {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
@@ -381,7 +366,7 @@ public final class CSSelect: NSObject {
     
     public init(_ swiftValue: Select) {
         
-        self.attributeType = .UndefinedAttributeType
+        self.attributeType = .undefinedAttributeType
         self.selectTerms = swiftValue.selectTerms
         self.bridgeToSwift = swiftValue
         super.init()
diff --git a/Sources/ObjectiveC/CSSetupResult.swift b/Sources/ObjectiveC/CSSetupResult.swift
index 12d5ac8..fe2d383 100644
--- a/Sources/ObjectiveC/CSSetupResult.swift
+++ b/Sources/ObjectiveC/CSSetupResult.swift
@@ -76,15 +76,15 @@ public final class CSSetupResult: NSObject {
      - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
      */
     @objc
-    public func handleSuccess(@noescape success: (storage: CSStorageInterface) -> Void, @noescape failure: (error: NSError) -> Void) {
+    public func handleSuccess(_ success: (_ storage: CSStorageInterface) -> Void, failure: (_ error: NSError) -> Void) {
         
         if let storage = self.storage {
             
-            success(storage: storage)
+            success(storage)
         }
         else {
             
-            failure(error: self.error!)
+            failure(self.error!)
         }
     }
     
@@ -96,13 +96,13 @@ public final class CSSetupResult: NSObject {
      - parameter success: the block to execute on success. The block passes a `BOOL` argument that indicates if there were any changes made.
      */
     @objc
-    public func handleSuccess(@noescape success: (storage: CSStorageInterface) -> Void) {
+    public func handleSuccess(_ success: (_ storage: CSStorageInterface) -> Void) {
         
         guard let storage = self.storage else {
             
             return
         }
-        success(storage: storage)
+        success(storage)
     }
     
     /**
@@ -113,13 +113,13 @@ public final class CSSetupResult: NSObject {
      - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actual error.
      */
     @objc
-    public func handleFailure(@noescape failure: (error: NSError) -> Void) {
+    public func handleFailure(_ failure: (_ error: NSError) -> Void) {
         
         guard let error = self.error else {
             
             return
         }
-        failure(error: error)
+        failure(error)
     }
     
     
@@ -134,7 +134,7 @@ public final class CSSetupResult: NSObject {
         return self.isSuccess.hashValue ^ self.error!.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSSetupResult else {
             
@@ -146,21 +146,21 @@ public final class CSSetupResult: NSObject {
 
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
     // MARK: CoreStoreObjectiveCType
     
-    public required init(_ swiftValue: SetupResult) {
+    public required init(_ swiftValue: SetupResult) where T: CoreStoreSwiftType, T.ObjectiveCType: CSStorageInterface {
         
         switch swiftValue {
             
-        case .Success(let storage):
+        case .success(let storage):
             self.storage = storage.bridgeToObjectiveC
             self.error = nil
             
-        case .Failure(let error):
+        case .failure(let error):
             self.storage = nil
             self.error = error.bridgeToObjectiveC
         }
diff --git a/Sources/ObjectiveC/CSStorageInterface.swift b/Sources/ObjectiveC/CSStorageInterface.swift
index 999f5b3..44681f3 100644
--- a/Sources/ObjectiveC/CSStorageInterface.swift
+++ b/Sources/ObjectiveC/CSStorageInterface.swift
@@ -53,7 +53,7 @@ public protocol CSStorageInterface {
      The options dictionary for the `NSPersistentStore`
      */
     @objc
-    var storeOptions: [String: AnyObject]? { get }
+    var storeOptions: [AnyHashable: Any]? { get }
 }
 
 
@@ -70,22 +70,22 @@ public enum CSLocalStorageOptions: Int {
     /**
      Tells the `DataStack` that the store should not be migrated or recreated, and should simply fail on model mismatch
      */
-    case None = 0
+    case none = 0
     
     /**
      Tells the `DataStack` to delete and recreate the store on model mismatch, otherwise exceptions will be thrown on failure instead
      */
-    case RecreateStoreOnModelMismatch = 1
+    case recreateStoreOnModelMismatch = 1
     
     /**
      Tells the `DataStack` to prevent progressive migrations for the store
      */
-    case PreventProgressiveMigration = 2
+    case preventProgressiveMigration = 2
     
     /**
      Tells the `DataStack` to allow lightweight migration for the store when added synchronously
      */
-    case AllowSynchronousLightweightMigration = 4
+    case allowSynchronousLightweightMigration = 4
 }
 
 
@@ -103,13 +103,13 @@ public protocol CSLocalStorage: CSStorageInterface {
      The `NSURL` that points to the store file
      */
     @objc
-    var fileURL: NSURL { get }
+    var fileURL: URL { get }
     
     /**
      The `NSBundle`s from which to search mapping models for migrations
      */
     @objc
-    var mappingModelBundles: [NSBundle] { get }
+    var mappingModelBundles: [Bundle] { get }
     
     /**
      Options that tell the `CSDataStack` how to setup the persistent store
@@ -121,5 +121,5 @@ public protocol CSLocalStorage: CSStorageInterface {
      Called by the `CSDataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. Implementers can use the `sourceModel` to perform necessary store operations. (SQLite stores for example, can convert WAL journaling mode to DELETE before deleting)
      */
     @objc
-    func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel?, error: NSErrorPointer) -> Bool
+    func eraseStorageAndWait(metadata: NSDictionary, soureModelHint: NSManagedObjectModel?, error: NSErrorPointer) -> Bool
 }
diff --git a/Sources/ObjectiveC/CSSynchronousDataTransaction.swift b/Sources/ObjectiveC/CSSynchronousDataTransaction.swift
index 9403294..8a8f7ed 100644
--- a/Sources/ObjectiveC/CSSynchronousDataTransaction.swift
+++ b/Sources/ObjectiveC/CSSynchronousDataTransaction.swift
@@ -58,13 +58,14 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
      - returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
      */
     @objc
-    public func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
+    @discardableResult
+    public func beginSynchronous(_ closure: @escaping (_ transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? {
         
         return bridge {
             
             self.bridgeToSwift.beginSynchronous { (transaction) in
                 
-                closure(transaction: transaction.bridgeToObjectiveC)
+                closure(transaction.bridgeToObjectiveC)
             }
         }
     }
@@ -74,7 +75,7 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
@@ -87,7 +88,7 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
      - returns: a new `NSManagedObject` instance of the specified entity type.
      */
     @objc
-    public override func createInto(into: CSInto) -> AnyObject {
+    public override func createInto(_ into: CSInto) -> Any {
         
         return self.bridgeToSwift.create(into.bridgeToSwift)
     }
@@ -99,8 +100,7 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
      - returns: an editable proxy for the specified `NSManagedObject`.
      */
     @objc
-    @warn_unused_result
-    public override func editObject(object: NSManagedObject?) -> AnyObject? {
+    public override func editObject(_ object: NSManagedObject?) -> Any? {
         
         return self.bridgeToSwift.edit(object)
     }
@@ -113,8 +113,7 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
      - returns: an editable proxy for the specified `NSManagedObject`.
      */
     @objc
-    @warn_unused_result
-    public override func editInto(into: CSInto, objectID: NSManagedObjectID) -> AnyObject? {
+    public override func editInto(_ into: CSInto, objectID: NSManagedObjectID) -> Any? {
         
         return self.bridgeToSwift.edit(into.bridgeToSwift, objectID)
     }
@@ -125,7 +124,7 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
      - parameter object: the `NSManagedObject` type to be deleted
      */
     @objc
-    public override func deleteObject(object: NSManagedObject?) {
+    public override func deleteObject(_ object: NSManagedObject?) {
         
         return self.bridgeToSwift.delete(object)
     }
@@ -135,7 +134,7 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
      
      - parameter objects: the `NSManagedObject`s to be deleted
      */
-    public override func deleteObjects(objects: [NSManagedObject]) {
+    public override func deleteObjects(_ objects: [NSManagedObject]) {
         
         self.bridgeToSwift.delete(objects)
     }
diff --git a/Sources/ObjectiveC/CSTweak.swift b/Sources/ObjectiveC/CSTweak.swift
index 5c9864f..5e0654b 100644
--- a/Sources/ObjectiveC/CSTweak.swift
+++ b/Sources/ObjectiveC/CSTweak.swift
@@ -41,7 +41,7 @@ public final class CSTweak: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
      The block to customize the `NSFetchRequest`
      */
     @objc
-    public var block: (fetchRequest: NSFetchRequest) -> Void {
+    public var block: (_ fetchRequest: NSFetchRequest) -> Void {
         
         return self.bridgeToSwift.closure
     }
@@ -53,7 +53,7 @@ public final class CSTweak: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
      - parameter block: the block to customize the `NSFetchRequest`
      */
     @objc
-    public convenience init(block: (fetchRequest: NSFetchRequest) -> Void) {
+    public convenience init(block: @escaping (_ fetchRequest: NSFetchRequest) -> Void) {
         
         self.init(Tweak(block))
     }
@@ -63,14 +63,14 @@ public final class CSTweak: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
     // MARK: CSFetchClause, CSQueryClause, CSDeleteClause
     
     @objc
-    public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
+    public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) {
         
         self.bridgeToSwift.applyToFetchRequest(fetchRequest)
     }
diff --git a/Sources/ObjectiveC/CSUnsafeDataTransaction.swift b/Sources/ObjectiveC/CSUnsafeDataTransaction.swift
index 57769c4..44bc587 100644
--- a/Sources/ObjectiveC/CSUnsafeDataTransaction.swift
+++ b/Sources/ObjectiveC/CSUnsafeDataTransaction.swift
@@ -43,11 +43,11 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
      - parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block.
      */
     @objc
-    public func commit(completion: ((result: CSSaveResult) -> Void)?) {
+    public func commit(_ completion: ((_ result: CSSaveResult) -> Void)?) {
         
         self.bridgeToSwift.commit { (result) in
             
-            completion?(result: result.bridgeToObjectiveC)
+            completion?(result.bridgeToObjectiveC)
         }
     }
     
@@ -110,7 +110,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
      - parameter closure: the closure where changes can be made prior to the flush
      */
     @objc
-    public func flush(block: () -> Void) {
+    public func flush(_ block: () -> Void) {
         
         self.bridgeToSwift.flush {
             
@@ -125,7 +125,6 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
      - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
      */
     @objc
-    @warn_unused_result
     public func beginUnsafe() -> CSUnsafeDataTransaction {
         
         return bridge {
@@ -141,8 +140,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
      - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made.
      */
     @objc
-    @warn_unused_result
-    public func beginUnsafeWithSupportsUndo(supportsUndo: Bool) -> CSUnsafeDataTransaction {
+    public func beginUnsafeWithSupportsUndo(_ supportsUndo: Bool) -> CSUnsafeDataTransaction {
         
         return bridge {
             
@@ -168,7 +166,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
diff --git a/Sources/ObjectiveC/CSWhere.swift b/Sources/ObjectiveC/CSWhere.swift
index 15a4f12..ea1926a 100644
--- a/Sources/ObjectiveC/CSWhere.swift
+++ b/Sources/ObjectiveC/CSWhere.swift
@@ -53,7 +53,6 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
         fetchAllFrom:CSFromClass([MyPersonEntity class])
         fetchClauses:@[CSWhereValue(YES)]]];
      ```
-     
      - parameter value: the boolean value for the predicate
      */
     @objc
@@ -70,7 +69,6 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
         fetchAllFrom:CSFromClass([MyPersonEntity class])
         fetchClauses:@[CSWherePredicate(predicate)]];
      ```
-     
      - parameter format: the format string for the predicate
      - parameter argumentArray: the arguments for `format`
      */
@@ -123,7 +121,7 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
         return self.bridgeToSwift.hashValue
     }
     
-    public override func isEqual(object: AnyObject?) -> Bool {
+    public override func isEqual(_ object: Any?) -> Bool {
         
         guard let object = object as? CSWhere else {
             
@@ -134,14 +132,14 @@ public final class CSWhere: NSObject, CSFetchClause, CSQueryClause, CSDeleteClau
     
     public override var description: String {
         
-        return "(\(String(reflecting: self.dynamicType))) \(self.bridgeToSwift.coreStoreDumpString)"
+        return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
     }
     
     
     // MARK: CSFetchClause, CSQueryClause, CSDeleteClause
     
     @objc
-    public func applyToFetchRequest(fetchRequest: NSFetchRequest) {
+    public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) {
         
         self.bridgeToSwift.applyToFetchRequest(fetchRequest)
     }
diff --git a/Sources/ObjectiveC/CoreStoreBridge.swift b/Sources/ObjectiveC/CoreStoreBridge.swift
index fbb270c..3d94843 100644
--- a/Sources/ObjectiveC/CoreStoreBridge.swift
+++ b/Sources/ObjectiveC/CoreStoreBridge.swift
@@ -79,17 +79,17 @@ public extension CoreStoreSwiftType where ObjectiveCType: CoreStoreObjectiveCTyp
 
 // MARK: - Internal
 
-internal func bridge(@noescape closure: () -> T) -> T.ObjectiveCType {
+internal func bridge(_ closure: () -> T) -> T.ObjectiveCType where T.ObjectiveCType: CoreStoreObjectiveCType, T == T.ObjectiveCType.SwiftType {
     
     return closure().bridgeToObjectiveC
 }
 
-internal func bridge(@noescape closure: () -> T?) -> T.ObjectiveCType? {
+internal func bridge(_ closure: () -> T?) -> T.ObjectiveCType? where T.ObjectiveCType: CoreStoreObjectiveCType, T == T.ObjectiveCType.SwiftType {
     
     return closure()?.bridgeToObjectiveC
 }
 
-internal func bridge(@noescape closure: () throws -> T) throws -> T.ObjectiveCType {
+internal func bridge(_ closure: () throws -> T) throws -> T.ObjectiveCType where T.ObjectiveCType: CoreStoreObjectiveCType, T == T.ObjectiveCType.SwiftType {
     
     do {
         
@@ -101,7 +101,7 @@ internal func bridge Void) throws {
+internal func bridge(_ closure: () throws -> Void) throws {
     
     do {
         
@@ -113,86 +113,62 @@ internal func bridge(@noescape closure: () throws -> Void) throws {
     }
 }
 
-internal func bridge(error: NSErrorPointer, @noescape _ closure: () throws -> T) -> T.ObjectiveCType? {
+internal func bridge(_ error: NSErrorPointer, _ closure: () throws -> T) -> T.ObjectiveCType? {
     
     do {
         
         let result = try closure()
-        if error != nil {
-            
-            error.memory = nil
-        }
+        error?.pointee = nil
         return result.bridgeToObjectiveC
     }
     catch let swiftError {
         
-        if error != nil {
-            
-            error.memory = swiftError.bridgeToObjectiveC
-        }
+        error?.pointee = swiftError.bridgeToObjectiveC
         return nil
     }
 }
 
-internal func bridge(error: NSErrorPointer, @noescape _ closure: () throws -> Void) -> Bool {
+internal func bridge(_ error: NSErrorPointer, _ closure: () throws -> Void) -> Bool {
     
     do {
         
         try closure()
-        if error != nil {
-            
-            error.memory = nil
-        }
+        error?.pointee = nil
         return true
     }
     catch let swiftError {
         
-        if error != nil {
-            
-            error.memory = swiftError.bridgeToObjectiveC
-        }
+        error?.pointee = swiftError.bridgeToObjectiveC
         return false
     }
 }
 
-internal func bridge(error: NSErrorPointer, @noescape _ closure: () throws -> T?) -> T? {
+internal func bridge(_ error: NSErrorPointer, _ closure: () throws -> T?) -> T? {
     
     do {
         
         let result = try closure()
-        if error != nil {
-            
-            error.memory = nil
-        }
+        error?.pointee = nil
         return result
     }
     catch let swiftError {
         
-        if error != nil {
-            
-            error.memory = swiftError.bridgeToObjectiveC
-        }
+        error?.pointee = swiftError.bridgeToObjectiveC
         return nil
     }
 }
 
-internal func bridge(error: NSErrorPointer, @noescape _ closure: () throws -> [T]) -> [T.ObjectiveCType]? {
+internal func bridge(_ error: NSErrorPointer, _ closure: () throws -> [T]) -> [T.ObjectiveCType]? {
     
     do {
         
         let result = try closure()
-        if error != nil {
-            
-            error.memory = nil
-        }
+        error?.pointee = nil
         return result.map { $0.bridgeToObjectiveC }
     }
     catch let swiftError {
         
-        if error != nil {
-            
-            error.memory = swiftError.bridgeToObjectiveC
-        }
+        error?.pointee = swiftError.bridgeToObjectiveC
         return nil
     }
 }
diff --git a/Sources/ObjectiveC/NSFetchedResultsController+ObjectiveC.swift b/Sources/ObjectiveC/NSFetchedResultsController+ObjectiveC.swift
index 59d6cec..66dee61 100644
--- a/Sources/ObjectiveC/NSFetchedResultsController+ObjectiveC.swift
+++ b/Sources/ObjectiveC/NSFetchedResultsController+ObjectiveC.swift
@@ -29,38 +29,78 @@ import CoreData
 
 #if os(iOS) || os(watchOS) || os(tvOS)
 
-// MARK: - NSFetchedResultsController
+// MARK: - CSDataStack
 
-public extension NSFetchedResultsController {
+public extension CSDataStack {
     
     /**
-     Utility for creating an `NSFetchedResultsController` from a `CSDataStack`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `CSListMonitor`s abstractio
+     Utility for creating an `NSFetchedResultsController` from the `CSDataStack`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `CSListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `-performFetch:` on the created `NSFetchedResultsController`.
      
-     - parameter dataStack: the `CSDataStack` to observe objects from
-     - parameter fetchRequest: the `NSFetchRequest` instance to use with the `NSFetchedResultsController`
-     - parameter from: an optional `CSFrom` clause indicating the entity type. If not specified, the `fetchRequest` argument's `entity` property should already be set.
+     - parameter from: a `CSFrom` clause indicating the entity type
      - parameter sectionBy: a `CSSectionBy` 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 `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
+     - parameter fetchClauses: a series of `CSFetchClause` instances for fetching the object list. Accepts `CSWhere`, `CSOrderBy`, and `CSTweak` clauses.
+     - returns: an `NSFetchedResultsController` that observes the `CSDataStack`
      */
     @objc
-    public static func cs_createForStack(dataStack: CSDataStack, fetchRequest: NSFetchRequest, from: CSFrom?, sectionBy: CSSectionBy?, fetchClauses: [CSFetchClause]) -> NSFetchedResultsController {
+    public func createFetchedResultsControllerFrom(_ from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> NSFetchedResultsController {
         
-        return CoreStoreFetchedResultsController(
-            context: dataStack.bridgeToSwift.mainContext,
-            fetchRequest: fetchRequest,
-            from: from?.bridgeToSwift,
-            sectionBy: sectionBy?.bridgeToSwift,
-            applyFetchClauses: { fetchRequest in
-                
-                fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
-
-                CoreStore.assert(
-                    fetchRequest.sortDescriptors?.isEmpty == false,
-                    "An \(cs_typeName(NSFetchedResultsController)) requires a sort information. Specify from a \(cs_typeName(CSOrderBy)) clause or any custom \(cs_typeName(CSFetchClause)) that provides a sort descriptor."
-                )
-            }
+        return createFRC(
+            fromContext: self.bridgeToSwift.mainContext,
+            from: from,
+            sectionBy: sectionBy,
+            fetchClauses: fetchClauses
         )
     }
 }
+    
+    
+// MARK: - CSUnsafeDataTransaction
+
+public extension CSUnsafeDataTransaction {
+    
+    /**
+     Utility for creating an `NSFetchedResultsController` from the `CSUnsafeDataTransaction`. This is useful when an `NSFetchedResultsController` is preferred over the overhead of `CSListMonitor`s abstraction.
+     - Note: It is the caller's responsibility to call `-performFetch:` on the created `NSFetchedResultsController`.
+     
+     - parameter from: a `CSFrom` clause indicating the entity type
+     - parameter sectionBy: a `CSSectionBy` 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: an `NSFetchedResultsController` that observes an `CSUnsafeDataTransaction`
+     */
+    @objc
+    public func createFetchedResultsControllerFrom(_ from: CSFrom, sectionBy: CSSectionBy, fetchClauses: [CSFetchClause]) -> NSFetchedResultsController {
+        
+        return createFRC(
+            fromContext: self.bridgeToSwift.context,
+            from: from,
+            sectionBy: sectionBy,
+            fetchClauses: fetchClauses
+        )
+    }
+}
+    
+    
+// MARK: - Private
+
+fileprivate func createFRC(fromContext context: NSManagedObjectContext, from: CSFrom? = nil, sectionBy: CSSectionBy?, fetchClauses: [CSFetchClause]) -> NSFetchedResultsController {
+    
+    let controller = CoreStoreFetchedResultsController(
+        context: context,
+        fetchRequest: CoreStoreFetchRequest().dynamicCast(),
+        from: from?.bridgeToSwift.upcast(),
+        sectionBy: sectionBy?.bridgeToSwift,
+        applyFetchClauses: { (fetchRequest) in
+            
+            fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest) }
+            
+            CoreStore.assert(
+                fetchRequest.sortDescriptors?.isEmpty == false,
+                "An \(cs_typeName(NSFetchedResultsController.self)) requires a sort information. Specify from a \(cs_typeName(CSOrderBy.self)) clause or any custom \(cs_typeName(CSFetchClause.self)) that provides a sort descriptor."
+            )
+        }
+    )
+    return controller.dynamicCast()
+}
 
 #endif
diff --git a/Sources/ObjectiveC/NSManagedObject+ObjectiveC.swift b/Sources/ObjectiveC/NSManagedObject+ObjectiveC.swift
index dc6ef8b..05d584c 100644
--- a/Sources/ObjectiveC/NSManagedObject+ObjectiveC.swift
+++ b/Sources/ObjectiveC/NSManagedObject+ObjectiveC.swift
@@ -38,8 +38,7 @@ public extension NSManagedObject {
      - returns: the primitive value for the KVC key
      */
     @objc
-    @warn_unused_result
-    public func cs_accessValueForKVCKey(KVCKey: KeyPath) -> AnyObject? {
+    public func cs_accessValueForKVCKey(_ KVCKey: KeyPath) -> Any? {
         
         return self.accessValueForKVCKey(KVCKey)
     }
@@ -51,7 +50,7 @@ public extension NSManagedObject {
      - parameter KVCKey: the KVC key
      */
     @objc
-    public func cs_setValue(value: AnyObject?, forKVCKey KVCKey: KeyPath) {
+    public func cs_setValue(_ value: Any?, forKVCKey KVCKey: KeyPath) {
         
         self.setValue(value, forKVCKey: KVCKey)
     }
diff --git a/Sources/ObjectiveC/NSManagedObjectContext+ObjectiveC.swift b/Sources/ObjectiveC/NSManagedObjectContext+ObjectiveC.swift
index 701eb4f..91bd888 100644
--- a/Sources/ObjectiveC/NSManagedObjectContext+ObjectiveC.swift
+++ b/Sources/ObjectiveC/NSManagedObjectContext+ObjectiveC.swift
@@ -34,41 +34,41 @@ internal extension NSManagedObjectContext {
     // MARK: Internal
     
     @nonobjc
-    internal func fetchOne(from: CSFrom, _ fetchClauses: [CSFetchClause]) -> NSManagedObject? {
+    internal func fetchOne(_ from: CSFrom, _ fetchClauses: [CSFetchClause]) -> NSManagedObject? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.bridgeToSwift.applyToFetchRequest(fetchRequest, context: self)
         
         fetchRequest.fetchLimit = 1
-        fetchRequest.resultType = .ManagedObjectResultType
+        fetchRequest.resultType = .managedObjectResultType
         fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
         
         guard storeFound else {
             
             return nil
         }
-        return self.fetchOne(fetchRequest)
+        return self.fetchOne(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func fetchAll(from: CSFrom, _ fetchClauses: [CSFetchClause]) -> [NSManagedObject]? {
+    internal func fetchAll(_ from: CSFrom, _ fetchClauses: [CSFetchClause]) -> [T]? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.bridgeToSwift.applyToFetchRequest(fetchRequest, context: self)
         
         fetchRequest.fetchLimit = 0
-        fetchRequest.resultType = .ManagedObjectResultType
+        fetchRequest.resultType = .managedObjectResultType
         fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
         
         guard storeFound else {
             
             return nil
         }
-        return self.fetchAll(fetchRequest)
+        return self.fetchAll(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func fetchCount(from: CSFrom, _ fetchClauses: [CSFetchClause]) -> Int? {
+    internal func fetchCount(_ from: CSFrom, _ fetchClauses: [CSFetchClause]) -> Int? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.bridgeToSwift.applyToFetchRequest(fetchRequest, context: self)
@@ -78,51 +78,51 @@ internal extension NSManagedObjectContext {
             
             return nil
         }
-        return self.fetchCount(fetchRequest)
+        return self.fetchCount(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func fetchObjectID(from: CSFrom, _ fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
+    internal func fetchObjectID(_ from: CSFrom, _ fetchClauses: [CSFetchClause]) -> NSManagedObjectID? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.bridgeToSwift.applyToFetchRequest(fetchRequest, context: self)
         
         fetchRequest.fetchLimit = 1
-        fetchRequest.resultType = .ManagedObjectIDResultType
+        fetchRequest.resultType = .managedObjectIDResultType
         fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
         
         guard storeFound else {
             
             return nil
         }
-        return self.fetchObjectID(fetchRequest)
+        return self.fetchObjectID(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func fetchObjectIDs(from: CSFrom, _ fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
+    internal func fetchObjectIDs(_ from: CSFrom, _ fetchClauses: [CSFetchClause]) -> [NSManagedObjectID]? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.bridgeToSwift.applyToFetchRequest(fetchRequest, context: self)
         
         fetchRequest.fetchLimit = 0
-        fetchRequest.resultType = .ManagedObjectIDResultType
+        fetchRequest.resultType = .managedObjectIDResultType
         fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
         
         guard storeFound else {
             
             return nil
         }
-        return self.fetchObjectIDs(fetchRequest)
+        return self.fetchObjectIDs(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func deleteAll(from: CSFrom, _ deleteClauses: [CSDeleteClause]) -> Int? {
+    internal func deleteAll(_ from: CSFrom, _ deleteClauses: [CSDeleteClause]) -> Int? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.bridgeToSwift.applyToFetchRequest(fetchRequest, context: self)
         
         fetchRequest.fetchLimit = 0
-        fetchRequest.resultType = .ManagedObjectResultType
+        fetchRequest.resultType = .managedObjectResultType
         fetchRequest.returnsObjectsAsFaults = true
         fetchRequest.includesPropertyValues = false
         deleteClauses.forEach { $0.applyToFetchRequest(fetchRequest) }
@@ -131,11 +131,11 @@ internal extension NSManagedObjectContext {
             
             return nil
         }
-        return self.deleteAll(fetchRequest)
+        return self.deleteAll(fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func queryValue(from: CSFrom, _ selectClause: CSSelect, _ queryClauses: [CSQueryClause]) -> AnyObject? {
+    internal func queryValue(_ from: CSFrom, _ selectClause: CSSelect, _ queryClauses: [CSQueryClause]) -> Any? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.bridgeToSwift.applyToFetchRequest(fetchRequest, context: self)
@@ -150,11 +150,11 @@ internal extension NSManagedObjectContext {
             
             return nil
         }
-        return self.queryValue(selectTerms, fetchRequest: fetchRequest)
+        return self.queryValue(selectTerms, fetchRequest: fetchRequest.dynamicCast())
     }
     
     @nonobjc
-    internal func queryAttributes(from: CSFrom, _ selectClause: CSSelect, _ queryClauses: [CSQueryClause]) -> [[NSString: AnyObject]]? {
+    internal func queryAttributes(_ from: CSFrom, _ selectClause: CSSelect, _ queryClauses: [CSQueryClause]) -> [[String: Any]]? {
         
         let fetchRequest = CoreStoreFetchRequest()
         let storeFound = from.bridgeToSwift.applyToFetchRequest(fetchRequest, context: self)
@@ -168,6 +168,6 @@ internal extension NSManagedObjectContext {
             
             return nil
         }
-        return self.queryAttributes(fetchRequest)
+        return self.queryAttributes(fetchRequest.dynamicCast())
     }
 }
diff --git a/Sources/ObjectiveC/NSProgress+ObjectiveC.swift b/Sources/ObjectiveC/Progress+ObjectiveC.swift
similarity index 89%
rename from Sources/ObjectiveC/NSProgress+ObjectiveC.swift
rename to Sources/ObjectiveC/Progress+ObjectiveC.swift
index ee2c93c..5b1fdfb 100644
--- a/Sources/ObjectiveC/NSProgress+ObjectiveC.swift
+++ b/Sources/ObjectiveC/Progress+ObjectiveC.swift
@@ -1,5 +1,5 @@
 //
-//  NSProgress+ObjectiveC.swift
+//  Progress+ObjectiveC.swift
 //  CoreStore
 //
 //  Copyright © 2016 John Rommel Estropia
@@ -26,9 +26,9 @@
 import Foundation
 
 
-// MARK: - NSProgress
+// MARK: - Progress
 
-public extension NSProgress {
+public extension Progress {
     
     /**
      Sets a closure that the `NSProgress` calls whenever its `fractionCompleted` changes. You can use this instead of setting up KVO.
@@ -36,7 +36,7 @@ public extension NSProgress {
      - parameter closure: the closure to execute on progress change
      */
     @objc
-    public func cs_setProgressHandler(closure: ((progress: NSProgress) -> Void)?) {
+    public func cs_setProgressHandler(_ closure: ((_ progress: Progress) -> Void)?) {
         
         self.setProgressHandler(closure)
     }
diff --git a/Sources/Observing/CoreStore+Observing.swift b/Sources/Observing/CoreStore+Observing.swift
index b956d60..72f4b53 100644
--- a/Sources/Observing/CoreStore+Observing.swift
+++ b/Sources/Observing/CoreStore+Observing.swift
@@ -39,8 +39,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(object: T) -> ObjectMonitor {
+    public static func monitorObject(_ object: T) -> ObjectMonitor {
         
         return self.defaultStack.monitorObject(object)
     }
@@ -52,8 +51,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(from: From, _ fetchClauses: FetchClause...) -> ListMonitor {
+    public static func monitorList(_ from: From, _ fetchClauses: FetchClause...) -> ListMonitor {
         
         return self.defaultStack.monitorList(from, fetchClauses)
     }
@@ -65,8 +63,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(from: From, _ fetchClauses: [FetchClause]) -> ListMonitor {
+    public static func monitorList(_ from: From, _ fetchClauses: [FetchClause]) -> ListMonitor {
         
         return self.defaultStack.monitorList(from, fetchClauses)
     }
@@ -78,7 +75,7 @@ public extension CoreStore {
      - parameter from: a `From` clause indicating the entity type
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      */
-    public static func monitorList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) {
+    public static func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) {
         
         self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
     }
@@ -90,7 +87,7 @@ public extension CoreStore {
      - parameter from: a `From` clause indicating the entity type
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      */
-    public static func monitorList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause])  {
+    public static func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause])  {
         
         self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
     }
@@ -103,8 +100,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(from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor {
+    public static func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor {
         
         return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
     }
@@ -117,8 +113,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(from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor {
+    public static func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor {
         
         return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
     }
@@ -131,7 +126,7 @@ public extension CoreStore {
      - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      */
-    public static func monitorSectionedList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
+    public static func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
         
         self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
     }
@@ -144,7 +139,7 @@ public extension CoreStore {
      - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      */
-    public static func monitorSectionedList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
+    public static func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
         
         self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
     }
diff --git a/Sources/Observing/DataStack+Observing.swift b/Sources/Observing/DataStack+Observing.swift
index 4d08a90..5374b77 100644
--- a/Sources/Observing/DataStack+Observing.swift
+++ b/Sources/Observing/DataStack+Observing.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 #if os(iOS) || os(watchOS) || os(tvOS)
@@ -42,11 +39,10 @@ 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(object: T) -> ObjectMonitor {
+    public func monitorObject(_ object: T) -> ObjectMonitor {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
         )
         return ObjectMonitor(dataStack: self, object: object)
@@ -59,8 +55,7 @@ public extension DataStack {
      - 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(from: From, _ fetchClauses: FetchClause...) -> ListMonitor {
+    public func monitorList(_ from: From, _ fetchClauses: FetchClause...) -> ListMonitor {
         
         return self.monitorList(from, fetchClauses)
     }
@@ -72,11 +67,10 @@ public extension DataStack {
      - 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(from: From, _ fetchClauses: [FetchClause]) -> ListMonitor {
+    public func monitorList(_ from: From, _ fetchClauses: [FetchClause]) -> ListMonitor {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
         )
         return ListMonitor(
@@ -89,7 +83,7 @@ public extension DataStack {
                 
                 CoreStore.assert(
                     fetchRequest.sortDescriptors?.isEmpty == false,
-                    "An \(cs_typeName(NSFetchedResultsController)) requires a sort information. Specify from a \(cs_typeName(OrderBy)) clause or any custom \(cs_typeName(FetchClause)) that provides a sort descriptor."
+                    "An \(cs_typeName(ListMonitor.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
                 )
             }
         )
@@ -102,7 +96,7 @@ 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.
      */
-    public func monitorList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) {
+    public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) {
         
         self.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
     }
@@ -114,10 +108,10 @@ 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.
      */
-    public func monitorList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause])  {
+    public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause])  {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
         )
         _ = ListMonitor(
@@ -130,7 +124,7 @@ public extension DataStack {
                 
                 CoreStore.assert(
                     fetchRequest.sortDescriptors?.isEmpty == false,
-                    "An \(cs_typeName(NSFetchedResultsController)) requires a sort information. Specify from a \(cs_typeName(OrderBy)) clause or any custom \(cs_typeName(FetchClause)) that provides a sort descriptor."
+                    "An \(cs_typeName(ListMonitor.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
                 )
             },
             createAsynchronously: createAsynchronously
@@ -145,8 +139,7 @@ public extension DataStack {
      - 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(from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor {
+    public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor {
         
         return self.monitorSectionedList(from, sectionBy, fetchClauses)
     }
@@ -159,11 +152,10 @@ public extension DataStack {
      - 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(from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor {
+    public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
         )
         
@@ -177,7 +169,7 @@ public extension DataStack {
                 
                 CoreStore.assert(
                     fetchRequest.sortDescriptors?.isEmpty == false,
-                    "An \(cs_typeName(NSFetchedResultsController)) requires a sort information. Specify from a \(cs_typeName(OrderBy)) clause or any custom \(cs_typeName(FetchClause)) that provides a sort descriptor."
+                    "An \(cs_typeName(ListMonitor.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
                 )
             }
         )
@@ -191,7 +183,7 @@ 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.
      */
-    public func monitorSectionedList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
+    public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
         
         self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
     }
@@ -204,10 +196,10 @@ 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.
      */
-    public func monitorSectionedList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
+    public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to observe objects from \(cs_typeName(self)) outside the main thread."
         )
         
@@ -221,7 +213,7 @@ public extension DataStack {
                 
                 CoreStore.assert(
                     fetchRequest.sortDescriptors?.isEmpty == false,
-                    "An \(cs_typeName(NSFetchedResultsController)) requires a sort information. Specify from a \(cs_typeName(OrderBy)) clause or any custom \(cs_typeName(FetchClause)) that provides a sort descriptor."
+                    "An \(cs_typeName(ListMonitor.self)) requires a sort information. Specify from a \(cs_typeName(OrderBy.self)) clause or any custom \(cs_typeName(FetchClause.self)) that provides a sort descriptor."
                 )
             },
             createAsynchronously: createAsynchronously
diff --git a/Sources/Observing/ListMonitor.swift b/Sources/Observing/ListMonitor.swift
index 24cc7fd..38a4ec8 100644
--- a/Sources/Observing/ListMonitor.swift
+++ b/Sources/Observing/ListMonitor.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 #if os(iOS) || os(watchOS) || os(tvOS)
@@ -38,9 +35,9 @@ import CoreData
  The `ListMonitor` monitors changes to a list of `NSManagedObject` instances. Observers that implement the `ListObserver` protocol may then register themselves to the `ListMonitor`'s `addObserver(_:)` method:
  ```
  let monitor = CoreStore.monitorList(
-     From(MyPersonEntity),
+     From(),
      Where("title", isEqualTo: "Engineer"),
-     OrderBy(.Ascending("lastName"))
+     OrderBy(.ascending("lastName"))
  )
  monitor.addObserver(self)
  ```
@@ -56,10 +53,10 @@ import CoreData
  Creating a sectioned-list is also possible with the `monitorSectionedList(...)` method:
  ```
  let monitor = CoreStore.monitorSectionedList(
-     From(MyPersonEntity),
+     From(),
      SectionBy("age") { "Age \($0)" },
      Where("title", isEqualTo: "Engineer"),
-     OrderBy(.Ascending("lastName"))
+     OrderBy(.ascending("lastName"))
  )
  monitor.addObserver(self)
  ```
@@ -111,7 +108,7 @@ public final class ListMonitor: Hashable {
      */
     public subscript(sectionIndex: Int, itemIndex: Int) -> T {
         
-        return self[NSIndexPath(indexes: [sectionIndex, itemIndex], length: 2)]
+        return self[NSIndexPath(indexes: [sectionIndex, itemIndex], length: 2) as IndexPath]
     }
     
     /**
@@ -140,13 +137,13 @@ public final class ListMonitor: Hashable {
      - parameter indexPath: the `NSIndexPath` for the object. Using an `indexPath` with an invalid range will raise an exception.
      - returns: the `NSManagedObject` at the specified index path
      */
-    public subscript(indexPath: NSIndexPath) -> T {
+    public subscript(indexPath: IndexPath) -> T {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
-        return self.fetchedResultsController.objectAtIndexPath(indexPath) as! T
+        return self.fetchedResultsController.object(at: indexPath) as! T
     }
     
     /**
@@ -155,11 +152,11 @@ public final class ListMonitor: Hashable {
      - parameter indexPath: the `NSIndexPath` for the object. Using an `indexPath` with an invalid range will return `nil`.
      - returns: the `NSManagedObject` at the specified index path, or `nil` if out of bounds
      */
-    public subscript(safeIndexPath indexPath: NSIndexPath) -> T? {
+    public subscript(safeIndexPath indexPath: IndexPath) -> T? {
         
         return self[
-            safeSectionIndex: indexPath.indexAtPosition(0),
-            safeItemIndex: indexPath.indexAtPosition(1)
+            safeSectionIndex: indexPath[0],
+            safeItemIndex: indexPath[1]
         ]
     }
     
@@ -168,7 +165,6 @@ public final class ListMonitor: Hashable {
      
      - returns: `true` if at least one section exists, `false` otherwise
      */
-    @warn_unused_result
     public func hasSections() -> Bool {
         
         return self.sections().count > 0
@@ -179,7 +175,6 @@ public final class ListMonitor: Hashable {
      
      - returns: `true` if at least one object in any section exists, `false` otherwise
      */
-    @warn_unused_result
     public func hasObjects() -> Bool {
         
         return self.numberOfObjects() > 0
@@ -191,10 +186,9 @@ public final class ListMonitor: Hashable {
      - parameter section: the section index. Using an index outside the valid range will return `false`.
      - returns: `true` if at least one object in the specified section exists, `false` otherwise
      */
-    @warn_unused_result
-    public func hasObjectsInSection(section: Int) -> Bool {
+    public func hasObjectsInSection(_ section: Int) -> Bool {
         
-        return self.numberOfObjectsInSection(safeSectionIndex: section) > 0
+        return self.numberOfObjectsInSection(safeSectionIndex: section)! > 0
     }
     
     /**
@@ -202,11 +196,10 @@ public final class ListMonitor: Hashable {
      
      - returns: all objects in all sections
      */
-    @warn_unused_result
     public func objectsInAllSections() -> [T] {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
         return (self.fetchedResultsController.fetchedObjects as? [T]) ?? []
@@ -218,8 +211,7 @@ public final class ListMonitor: Hashable {
      - parameter section: the section index. Using an index outside the valid range will raise an exception.
      - returns: all objects in the specified section
      */
-    @warn_unused_result
-    public func objectsInSection(section: Int) -> [T] {
+    public func objectsInSection(_ section: Int) -> [T] {
         
         return (self.sectionInfoAtIndex(section).objects as? [T]) ?? []
     }
@@ -230,7 +222,6 @@ public final class ListMonitor: Hashable {
      - parameter section: the section index. Using an index outside the valid range will return `nil`.
      - returns: all objects in the specified section
      */
-    @warn_unused_result
     public func objectsInSection(safeSectionIndex section: Int) -> [T]? {
         
         return (self.sectionInfoAtIndex(safeSectionIndex: section)?.objects as? [T]) ?? []
@@ -241,11 +232,10 @@ public final class ListMonitor: Hashable {
      
      - returns: the number of sections
      */
-    @warn_unused_result
     public func numberOfSections() -> Int {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
         return self.fetchedResultsController.sections?.count ?? 0
@@ -256,11 +246,10 @@ public final class ListMonitor: Hashable {
      
      - returns: the number of objects in all sections
      */
-    @warn_unused_result
     public func numberOfObjects() -> Int {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
         return self.fetchedResultsController.fetchedObjects?.count ?? 0
@@ -272,8 +261,7 @@ public final class ListMonitor: Hashable {
      - parameter section: the section index. Using an index outside the valid range will raise an exception.
      - returns: the number of objects in the specified section
      */
-    @warn_unused_result
-    public func numberOfObjectsInSection(section: Int) -> Int {
+    public func numberOfObjectsInSection(_ section: Int) -> Int {
         
         return self.sectionInfoAtIndex(section).numberOfObjects
     }
@@ -284,7 +272,6 @@ public final class ListMonitor: Hashable {
      - parameter section: the section index. Using an index outside the valid range will return `nil`.
      - returns: the number of objects in the specified section
      */
-    @warn_unused_result
     public func numberOfObjectsInSection(safeSectionIndex section: Int) -> Int? {
         
         return self.sectionInfoAtIndex(safeSectionIndex: section)?.numberOfObjects
@@ -296,11 +283,10 @@ public final class ListMonitor: Hashable {
      - parameter section: the section index. Using an index outside the valid range will raise an exception.
      - returns: the `NSFetchedResultsSectionInfo` for the specified section
      */
-    @warn_unused_result
-    public func sectionInfoAtIndex(section: Int) -> NSFetchedResultsSectionInfo {
+    public func sectionInfoAtIndex(_ section: Int) -> NSFetchedResultsSectionInfo {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
         return self.fetchedResultsController.sections![section]
@@ -312,21 +298,19 @@ public final class ListMonitor: Hashable {
      - parameter section: the section index. Using an index outside the valid range will return `nil`.
      - returns: the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if the section index is out of bounds.
      */
-    @warn_unused_result
     public func sectionInfoAtIndex(safeSectionIndex section: Int) -> NSFetchedResultsSectionInfo? {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
         guard section >= 0 else {
             
             return nil
         }
-        guard let sections = self.fetchedResultsController.sections
-            where section < sections.count else {
-                
-                return nil
+        guard let sections = self.fetchedResultsController.sections, section < sections.count else {
+            
+            return nil
         }
         return sections[section]
     }
@@ -336,11 +320,10 @@ public final class ListMonitor: Hashable {
      
      - returns: the `NSFetchedResultsSectionInfo`s for all sections
      */
-    @warn_unused_result
     public func sections() -> [NSFetchedResultsSectionInfo] {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
         return self.fetchedResultsController.sections ?? []
@@ -353,14 +336,13 @@ public final class ListMonitor: Hashable {
      - parameter index: the index of the Section Index
      - returns: the target section for the specified "Section Index" title and index.
      */
-    @warn_unused_result
-    public func targetSectionForSectionIndex(title title: String, index: Int) -> Int {
+    public func targetSectionForSectionIndex(title: String, index: Int) -> Int {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
-        return self.fetchedResultsController.sectionForSectionIndexTitle(title, atIndex: index)
+        return self.fetchedResultsController.section(forSectionIndexTitle: title, at: index)
     }
     
     /**
@@ -368,11 +350,10 @@ public final class ListMonitor: Hashable {
      
      - returns: the section index titles for all sections
      */
-    @warn_unused_result
     public func sectionIndexTitles() -> [String] {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
         return self.fetchedResultsController.sectionIndexTitles
@@ -384,14 +365,13 @@ public final class ListMonitor: Hashable {
      - parameter object: the `NSManagedObject` to search the index of
      - returns: the index of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
      */
-    @warn_unused_result
-    public func indexOf(object: T) -> Int? {
+    public func indexOf(_ object: T) -> Int? {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
-        return (self.fetchedResultsController.fetchedObjects as? [T] ?? []).indexOf(object)
+        return (self.fetchedResultsController.fetchedObjects as? [T] ?? []).index(of: object)
     }
     
     /**
@@ -400,14 +380,13 @@ public final class ListMonitor: Hashable {
      - parameter object: the `NSManagedObject` to search the index of
      - returns: the `NSIndexPath` of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
      */
-    @warn_unused_result
-    public func indexPathOf(object: T) -> NSIndexPath? {
+    public func indexPathOf(_ object: T) -> IndexPath? {
         
         CoreStore.assert(
-            !self.isPendingRefetch || NSThread.isMainThread(),
+            !self.isPendingRefetch || Thread.isMainThread,
             "Attempted to access a \(cs_typeName(self)) outside the main thread while a refetch is in progress."
         )
-        return self.fetchedResultsController.indexPathForObject(object)
+        return self.fetchedResultsController.indexPath(forObject: object)
     }
     
     
@@ -424,7 +403,7 @@ public final class ListMonitor: Hashable {
      
      - parameter observer: a `ListObserver` to send change notifications to
      */
-    public func addObserver(observer: U) {
+    public func addObserver(_ observer: U) where U.ListEntityType == T {
         
         self.unregisterObserver(observer)
         self.registerObserver(
@@ -459,7 +438,7 @@ public final class ListMonitor: Hashable {
      
      - parameter observer: a `ListObjectObserver` to send change notifications to
      */
-    public func addObserver(observer: U) {
+    public func addObserver(_ observer: U) where U.ListEntityType == T {
         
         self.unregisterObserver(observer)
         self.registerObserver(
@@ -513,7 +492,7 @@ public final class ListMonitor: Hashable {
      
      - parameter observer: a `ListSectionObserver` to send change notifications to
      */
-    public func addObserver(observer: U) {
+    public func addObserver(_ observer: U) where U.ListEntityType == T {
         
         self.unregisterObserver(observer)
         self.registerObserver(
@@ -574,7 +553,7 @@ public final class ListMonitor: Hashable {
      
      - parameter observer: a `ListObserver` to unregister notifications to
      */
-    public func removeObserver(observer: U) {
+    public func removeObserver(_ observer: U) where U.ListEntityType == T {
         
         self.unregisterObserver(observer)
     }
@@ -594,7 +573,7 @@ public final class ListMonitor: Hashable {
      
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. Note that only specified clauses will be changed; unspecified clauses will use previous values.
      */
-    public func refetch(fetchClauses: FetchClause...) {
+    public func refetch(_ fetchClauses: FetchClause...) {
         
         self.refetch(fetchClauses)
     }
@@ -606,7 +585,7 @@ public final class ListMonitor: Hashable {
      
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. Note that only specified clauses will be changed; unspecified clauses will use previous values.
      */
-    public func refetch(fetchClauses: [FetchClause]) {
+    public func refetch(_ fetchClauses: [FetchClause]) {
         
         self.refetch { (fetchRequest) in
             
@@ -615,6 +594,29 @@ public final class ListMonitor: Hashable {
     }
     
     
+    // MARK: Equatable
+    
+    public static func == (lhs: ListMonitor, rhs: ListMonitor) -> Bool {
+        
+        return lhs === rhs
+    }
+    
+    public static func == (lhs: ListMonitor, rhs: ListMonitor) -> Bool {
+        
+        return lhs.fetchedResultsController === rhs.fetchedResultsController
+    }
+    
+    public static func ~= (lhs: ListMonitor, rhs: ListMonitor) -> Bool {
+        
+        return lhs === rhs
+    }
+    
+    public static func ~= (lhs: ListMonitor, rhs: ListMonitor) -> Bool {
+        
+        return lhs.fetchedResultsController === rhs.fetchedResultsController
+    }
+    
+    
     // MARK: Hashable
     
     public var hashValue: Int {
@@ -625,7 +627,7 @@ public final class ListMonitor: Hashable {
     
     // MARK: Internal
     
-    internal convenience init(dataStack: DataStack, from: From, sectionBy: SectionBy?, applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void) {
+    internal convenience init(dataStack: DataStack, from: From, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void) {
         
         self.init(
             context: dataStack.mainContext,
@@ -637,7 +639,7 @@ public final class ListMonitor: Hashable {
         )
     }
     
-    internal convenience init(dataStack: DataStack, from: From, sectionBy: SectionBy?, applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void, createAsynchronously: (ListMonitor) -> Void) {
+    internal convenience init(dataStack: DataStack, from: From, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void, createAsynchronously: @escaping (ListMonitor) -> Void) {
         
         self.init(
             context: dataStack.mainContext,
@@ -649,7 +651,7 @@ public final class ListMonitor: Hashable {
         )
     }
     
-    internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From, sectionBy: SectionBy?, applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void) {
+    internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void) {
         
         self.init(
             context: unsafeTransaction.context,
@@ -661,7 +663,7 @@ public final class ListMonitor: Hashable {
         )
     }
     
-    internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From, sectionBy: SectionBy?, applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void, createAsynchronously: (ListMonitor) -> Void) {
+    internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void, createAsynchronously: @escaping (ListMonitor) -> Void) {
         
         self.init(
             context: unsafeTransaction.context,
@@ -675,10 +677,10 @@ public final class ListMonitor: Hashable {
     
     internal func upcast() -> ListMonitor {
         
-        return unsafeBitCast(self, ListMonitor.self)
+        return unsafeBitCast(self, to: ListMonitor.self)
     }
     
-    internal func registerChangeNotification(notificationKey: UnsafePointer, name: String, toObserver observer: AnyObject, callback: (monitor: ListMonitor) -> Void) {
+    internal func registerChangeNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor) -> Void) {
         
         cs_setAssociatedRetainedObject(
             NotificationObserver(
@@ -690,7 +692,7 @@ public final class ListMonitor: Hashable {
                         
                         return
                     }
-                    callback(monitor: self)
+                    callback(self)
                 }
             ),
             forKey: notificationKey,
@@ -698,7 +700,7 @@ public final class ListMonitor: Hashable {
         )
     }
     
-    internal func registerObjectNotification(notificationKey: UnsafePointer, name: String, toObserver observer: AnyObject, callback: (monitor: ListMonitor, object: T, indexPath: NSIndexPath?, newIndexPath: NSIndexPath?) -> Void) {
+    internal func registerObjectNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor, _ object: T, _ indexPath: IndexPath?, _ newIndexPath: IndexPath?) -> Void) {
         
         cs_setAssociatedRetainedObject(
             NotificationObserver(
@@ -708,15 +710,15 @@ public final class ListMonitor: Hashable {
                     
                     guard let `self` = self,
                         let userInfo = note.userInfo,
-                        let object = userInfo[UserInfoKeyObject] as? T else {
+                        let object = userInfo[String(describing: NSManagedObject.self)] as? T else {
                             
                             return
                     }
                     callback(
-                        monitor: self,
-                        object: object,
-                        indexPath: userInfo[UserInfoKeyIndexPath] as? NSIndexPath,
-                        newIndexPath: userInfo[UserInfoKeyNewIndexPath] as? NSIndexPath
+                        self,
+                        object,
+                        userInfo[String(describing: IndexPath.self)] as? IndexPath,
+                        userInfo["\(String(describing: IndexPath.self)).New"] as? IndexPath
                     )
                 }
             ),
@@ -725,7 +727,7 @@ public final class ListMonitor: Hashable {
         )
     }
     
-    internal func registerSectionNotification(notificationKey: UnsafePointer, name: String, toObserver observer: AnyObject, callback: (monitor: ListMonitor, sectionInfo: NSFetchedResultsSectionInfo, sectionIndex: Int) -> Void) {
+    internal func registerSectionNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ListMonitor, _ sectionInfo: NSFetchedResultsSectionInfo, _ sectionIndex: Int) -> Void) {
         
         cs_setAssociatedRetainedObject(
             NotificationObserver(
@@ -735,16 +737,12 @@ public final class ListMonitor: Hashable {
                     
                     guard let `self` = self,
                         let userInfo = note.userInfo,
-                        let sectionInfo = userInfo[UserInfoKeySectionInfo] as? NSFetchedResultsSectionInfo,
-                        let sectionIndex = (userInfo[UserInfoKeySectionIndex] as? NSNumber)?.integerValue else {
+                        let sectionInfo = userInfo[String(describing: NSFetchedResultsSectionInfo.self)] as? NSFetchedResultsSectionInfo,
+                        let sectionIndex = (userInfo[String(describing: NSNumber.self)] as? NSNumber)?.intValue else {
                             
                             return
                     }
-                    callback(
-                        monitor: self,
-                        sectionInfo: sectionInfo,
-                        sectionIndex: sectionIndex
-                    )
+                    callback(self, sectionInfo, sectionIndex)
                 }
             ),
             forKey: notificationKey,
@@ -752,15 +750,15 @@ public final class ListMonitor: Hashable {
         )
     }
     
-    internal func registerObserver(observer: U, willChange: (observer: U, monitor: ListMonitor) -> Void, didChange: (observer: U, monitor: ListMonitor) -> Void, willRefetch: (observer: U, monitor: ListMonitor) -> Void, didRefetch: (observer: U, monitor: ListMonitor) -> Void) {
+    internal func registerObserver(_ observer: U, willChange: @escaping (_ observer: U, _ monitor: ListMonitor) -> Void, didChange: @escaping (_ observer: U, _ monitor: ListMonitor) -> Void, willRefetch: @escaping (_ observer: U, _ monitor: ListMonitor) -> Void, didRefetch: @escaping (_ observer: U, _ monitor: ListMonitor) -> Void) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to add an observer of type \(cs_typeName(observer)) outside the main thread."
         )
         self.registerChangeNotification(
             &self.willChangeListKey,
-            name: ListMonitorWillChangeListNotification,
+            name: Notification.Name.listMonitorWillChangeList,
             toObserver: observer,
             callback: { [weak observer] (monitor) -> Void in
                 
@@ -768,12 +766,12 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                willChange(observer: observer, monitor: monitor)
+                willChange(observer, monitor)
             }
         )
         self.registerChangeNotification(
             &self.didChangeListKey,
-            name: ListMonitorDidChangeListNotification,
+            name: Notification.Name.listMonitorDidChangeList,
             toObserver: observer,
             callback: { [weak observer] (monitor) -> Void in
                 
@@ -781,12 +779,12 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                didChange(observer: observer, monitor: monitor)
+                didChange(observer, monitor)
             }
         )
         self.registerChangeNotification(
             &self.willRefetchListKey,
-            name: ListMonitorWillRefetchListNotification,
+            name: Notification.Name.listMonitorWillRefetchList,
             toObserver: observer,
             callback: { [weak observer] (monitor) -> Void in
                 
@@ -794,12 +792,12 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                willRefetch(observer: observer, monitor: monitor)
+                willRefetch(observer, monitor)
             }
         )
         self.registerChangeNotification(
             &self.didRefetchListKey,
-            name: ListMonitorDidRefetchListNotification,
+            name: Notification.Name.listMonitorDidRefetchList,
             toObserver: observer,
             callback: { [weak observer] (monitor) -> Void in
                 
@@ -807,21 +805,21 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                didRefetch(observer: observer, monitor: monitor)
+                didRefetch(observer, monitor)
             }
         )
     }
     
-    internal func registerObserver(observer: U, didInsertObject: (observer: U, monitor: ListMonitor, object: T, toIndexPath: NSIndexPath) -> Void, didDeleteObject: (observer: U, monitor: ListMonitor, object: T, fromIndexPath: NSIndexPath) -> Void, didUpdateObject: (observer: U, monitor: ListMonitor, object: T, atIndexPath: NSIndexPath) -> Void, didMoveObject: (observer: U, monitor: ListMonitor, object: T, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) -> Void) {
+    internal func registerObserver(_ observer: U, didInsertObject: @escaping (_ observer: U, _ monitor: ListMonitor, _ object: T, _ toIndexPath: IndexPath) -> Void, didDeleteObject: @escaping (_ observer: U, _ monitor: ListMonitor, _ object: T, _ fromIndexPath: IndexPath) -> Void, didUpdateObject: @escaping (_ observer: U, _ monitor: ListMonitor, _ object: T, _ atIndexPath: IndexPath) -> Void, didMoveObject: @escaping (_ observer: U, _ monitor: ListMonitor, _ object: T, _ fromIndexPath: IndexPath, _ toIndexPath: IndexPath) -> Void) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to add an observer of type \(cs_typeName(observer)) outside the main thread."
         )
         
         self.registerObjectNotification(
             &self.didInsertObjectKey,
-            name: ListMonitorDidInsertObjectNotification,
+            name: Notification.Name.listMonitorDidInsertObject,
             toObserver: observer,
             callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
                 
@@ -829,17 +827,12 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                didInsertObject(
-                    observer: observer,
-                    monitor: monitor,
-                    object: object,
-                    toIndexPath: newIndexPath!
-                )
+                didInsertObject(observer, monitor, object, newIndexPath!)
             }
         )
         self.registerObjectNotification(
             &self.didDeleteObjectKey,
-            name: ListMonitorDidDeleteObjectNotification,
+            name: Notification.Name.listMonitorDidDeleteObject,
             toObserver: observer,
             callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
                 
@@ -847,17 +840,12 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                didDeleteObject(
-                    observer: observer,
-                    monitor: monitor,
-                    object: object,
-                    fromIndexPath: indexPath!
-                )
+                didDeleteObject(observer, monitor, object, indexPath!)
             }
         )
         self.registerObjectNotification(
             &self.didUpdateObjectKey,
-            name: ListMonitorDidUpdateObjectNotification,
+            name: Notification.Name.listMonitorDidUpdateObject,
             toObserver: observer,
             callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
                 
@@ -865,17 +853,12 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                didUpdateObject(
-                    observer: observer,
-                    monitor: monitor,
-                    object: object,
-                    atIndexPath: indexPath!
-                )
+                didUpdateObject(observer, monitor, object, indexPath!)
             }
         )
         self.registerObjectNotification(
             &self.didMoveObjectKey,
-            name: ListMonitorDidMoveObjectNotification,
+            name: Notification.Name.listMonitorDidMoveObject,
             toObserver: observer,
             callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
                 
@@ -883,27 +866,21 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                didMoveObject(
-                    observer: observer,
-                    monitor: monitor,
-                    object: object,
-                    fromIndexPath: indexPath!,
-                    toIndexPath: newIndexPath!
-                )
+                didMoveObject(observer, monitor, object, indexPath!, newIndexPath!)
             }
         )
     }
     
-    internal func registerObserver(observer: U, didInsertSection: (observer: U, monitor: ListMonitor, sectionInfo: NSFetchedResultsSectionInfo, toIndex: Int) -> Void, didDeleteSection: (observer: U, monitor: ListMonitor, sectionInfo: NSFetchedResultsSectionInfo, fromIndex: Int) -> Void) {
+    internal func registerObserver(_ observer: U, didInsertSection: @escaping (_ observer: U, _ monitor: ListMonitor, _ sectionInfo: NSFetchedResultsSectionInfo, _ toIndex: Int) -> Void, didDeleteSection: @escaping (_ observer: U, _ monitor: ListMonitor, _ sectionInfo: NSFetchedResultsSectionInfo, _ fromIndex: Int) -> Void) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to add an observer of type \(cs_typeName(observer)) outside the main thread."
         )
         
         self.registerSectionNotification(
             &self.didInsertSectionKey,
-            name: ListMonitorDidInsertSectionNotification,
+            name: Notification.Name.listMonitorDidInsertSection,
             toObserver: observer,
             callback: { [weak observer] (monitor, sectionInfo, sectionIndex) -> Void in
                 
@@ -911,17 +888,12 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                didInsertSection(
-                    observer: observer,
-                    monitor: monitor,
-                    sectionInfo: sectionInfo,
-                    toIndex: sectionIndex
-                )
+                didInsertSection(observer, monitor, sectionInfo, sectionIndex)
             }
         )
         self.registerSectionNotification(
             &self.didDeleteSectionKey,
-            name: ListMonitorDidDeleteSectionNotification,
+            name: Notification.Name.listMonitorDidDeleteSection,
             toObserver: observer,
             callback: { [weak observer] (monitor, sectionInfo, sectionIndex) -> Void in
                 
@@ -929,20 +901,15 @@ public final class ListMonitor: Hashable {
                     
                     return
                 }
-                didDeleteSection(
-                    observer: observer,
-                    monitor: monitor,
-                    sectionInfo: sectionInfo,
-                    fromIndex: sectionIndex
-                )
+                didDeleteSection(observer, monitor, sectionInfo, sectionIndex)
             }
         )
     }
     
-    internal func unregisterObserver(observer: AnyObject) {
+    internal func unregisterObserver(_ observer: AnyObject) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to remove an observer of type \(cs_typeName(observer)) outside the main thread."
         )
         let nilValue: AnyObject? = nil
@@ -960,10 +927,10 @@ public final class ListMonitor: Hashable {
         cs_setAssociatedRetainedObject(nilValue, forKey: &self.didDeleteSectionKey, inObject: observer)
     }
     
-    internal func refetch(applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void) {
+    internal func refetch(_ applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to refetch a \(cs_typeName(self)) outside the main thread."
         )
         
@@ -971,14 +938,14 @@ public final class ListMonitor: Hashable {
             
             self.isPendingRefetch = true
             
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                ListMonitorWillRefetchListNotification,
+            NotificationCenter.default.post(
+                name: Notification.Name.listMonitorWillRefetchList,
                 object: self
             )
         }
         self.applyFetchClauses = applyFetchClauses
         
-        self.taskGroup.notify(.Main) { [weak self] () -> Void in
+        self.taskGroup.notify(queue: .main) { [weak self] () -> Void in
             
             guard let `self` = self else {
                 
@@ -986,7 +953,7 @@ public final class ListMonitor: Hashable {
             }
             
             self.fetchedResultsControllerDelegate.enabled = false
-            self.applyFetchClauses(fetchRequest: self.fetchedResultsController.fetchRequest)
+            self.applyFetchClauses(self.fetchedResultsController.fetchRequest)
             
             self.transactionQueue.async { [weak self] in
                 
@@ -997,7 +964,7 @@ public final class ListMonitor: Hashable {
                 
                 try! self.fetchedResultsController.performFetchFromSpecifiedStores()
                 
-                GCDQueue.Main.async { [weak self] () -> Void in
+                DispatchQueue.main.async { [weak self] () -> Void in
                     
                     guard let `self` = self else {
                         
@@ -1007,8 +974,8 @@ public final class ListMonitor: Hashable {
                     self.fetchedResultsControllerDelegate.enabled = true
                     self.isPendingRefetch = false
                     
-                    NSNotificationCenter.defaultCenter().postNotificationName(
-                        ListMonitorDidRefetchListNotification,
+                    NotificationCenter.default.post(
+                        name: Notification.Name.listMonitorDidRefetchList,
                         object: self
                     )
                 }
@@ -1025,6 +992,10 @@ public final class ListMonitor: Hashable {
     
     // MARK: Private
     
+    fileprivate let fetchedResultsController: CoreStoreFetchedResultsController
+    fileprivate let taskGroup = DispatchGroup()
+    fileprivate let sectionIndexTransformer: (_ sectionName: KeyPath?) -> String?
+    
     private var willChangeListKey: Void?
     private var didChangeListKey: Void?
     private var willRefetchListKey: Void?
@@ -1038,14 +1009,11 @@ public final class ListMonitor: Hashable {
     private var didInsertSectionKey: Void?
     private var didDeleteSectionKey: Void?
     
-    private let fetchedResultsController: CoreStoreFetchedResultsController
-    private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
-    private let sectionIndexTransformer: (sectionName: KeyPath?) -> String?
+    private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
     private var observerForWillChangePersistentStore: NotificationObserver!
     private var observerForDidChangePersistentStore: NotificationObserver!
-    private let taskGroup = GCDGroup()
-    private let transactionQueue: GCDQueue
-    private var applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void
+    private let transactionQueue: DispatchQueue
+    private var applyFetchClauses: (_ fetchRequest: NSFetchRequest) -> Void
     
     private var isPersistentStoreChanging: Bool = false {
         
@@ -1068,24 +1036,24 @@ public final class ListMonitor: Hashable {
         }
     }
     
-    private init(context: NSManagedObjectContext, transactionQueue: GCDQueue, from: From, sectionBy: SectionBy?, applyFetchClauses: (fetchRequest: NSFetchRequest) -> Void, createAsynchronously: ((ListMonitor) -> Void)?) {
+    private init(context: NSManagedObjectContext, transactionQueue: DispatchQueue, from: From, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest) -> Void, createAsynchronously: ((ListMonitor) -> Void)?) {
         
         let fetchRequest = CoreStoreFetchRequest()
         fetchRequest.fetchLimit = 0
-        fetchRequest.resultType = .ManagedObjectResultType
+        fetchRequest.resultType = .managedObjectResultType
         fetchRequest.fetchBatchSize = 20
         fetchRequest.includesPendingChanges = false
         fetchRequest.shouldRefreshRefetchedObjects = true
         
         let fetchedResultsController = CoreStoreFetchedResultsController(
             context: context,
-            fetchRequest: fetchRequest,
+            fetchRequest: fetchRequest.dynamicCast(),
             from: from,
             sectionBy: sectionBy,
             applyFetchClauses: applyFetchClauses
         )
         
-        let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate()
+        let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate()
         
         self.fetchedResultsController = fetchedResultsController
         self.fetchedResultsControllerDelegate = fetchedResultsControllerDelegate
@@ -1110,9 +1078,9 @@ public final class ListMonitor: Hashable {
         }
         
         self.observerForWillChangePersistentStore = NotificationObserver(
-            notificationName: NSPersistentStoreCoordinatorStoresWillChangeNotification,
+            notificationName: NSNotification.Name.NSPersistentStoreCoordinatorStoresWillChange,
             object: coordinator,
-            queue: NSOperationQueue.mainQueue(),
+            queue: OperationQueue.main,
             closure: { [weak self] (note) -> Void in
                 
                 guard let `self` = self else {
@@ -1122,8 +1090,8 @@ public final class ListMonitor: Hashable {
                 
                 self.isPersistentStoreChanging = true
                 
-                guard let removedStores = (note.userInfo?[NSRemovedPersistentStoresKey] as? [NSPersistentStore]).flatMap(Set.init)
-                    where !Set((self.fetchedResultsController.fetchRequest as! CoreStoreFetchRequest).safeAffectedStores ?? []).intersect(removedStores).isEmpty else {
+                guard let removedStores = (note.userInfo?[NSRemovedPersistentStoresKey] as? [NSPersistentStore]).flatMap(Set.init),
+                    !Set((self.fetchedResultsController.fetchRequest as Any as! CoreStoreFetchRequest).safeAffectedStores ?? []).intersection(removedStores).isEmpty else {
                         
                         return
                 }
@@ -1132,9 +1100,9 @@ public final class ListMonitor: Hashable {
         )
         
         self.observerForDidChangePersistentStore = NotificationObserver(
-            notificationName: NSPersistentStoreCoordinatorStoresDidChangeNotification,
+            notificationName: NSNotification.Name.NSPersistentStoreCoordinatorStoresDidChange,
             object: coordinator,
-            queue: NSOperationQueue.mainQueue(),
+            queue: OperationQueue.main,
             closure: { [weak self] (note) -> Void in
                 
                 guard let `self` = self else {
@@ -1144,9 +1112,9 @@ public final class ListMonitor: Hashable {
                 
                 if !self.isPendingRefetch {
                     
-                    let previousStores = Set((self.fetchedResultsController.fetchRequest as! CoreStoreFetchRequest).safeAffectedStores ?? [])
+                    let previousStores = Set((self.fetchedResultsController.fetchRequest as Any as! CoreStoreFetchRequest).safeAffectedStores ?? [])
                     let currentStores = previousStores
-                        .subtract(note.userInfo?[NSRemovedPersistentStoresKey] as? [NSPersistentStore] ?? [])
+                        .subtracting(note.userInfo?[NSRemovedPersistentStoresKey] as? [NSPersistentStore] ?? [])
                         .union(note.userInfo?[NSAddedPersistentStoresKey] as? [NSPersistentStore] ?? [])
                     
                     if previousStores != currentStores {
@@ -1164,7 +1132,7 @@ public final class ListMonitor: Hashable {
             transactionQueue.async {
                 
                 try! fetchedResultsController.performFetchFromSpecifiedStores()
-                self.taskGroup.notify(.Main) {
+                self.taskGroup.notify(queue: .main) {
                     
                     createAsynchronously(self)
                 }
@@ -1178,109 +1146,80 @@ public final class ListMonitor: Hashable {
 }
 
 
-// MARK: - ListMonitor: Equatable
-
-@warn_unused_result
-public func == (lhs: ListMonitor, rhs: ListMonitor) -> Bool {
-    
-    return lhs === rhs
-}
-
-@warn_unused_result
-public func == (lhs: ListMonitor, rhs: ListMonitor) -> Bool {
-    
-    return lhs.fetchedResultsController === rhs.fetchedResultsController
-}
-
-@warn_unused_result
-public func ~= (lhs: ListMonitor, rhs: ListMonitor) -> Bool {
-    
-    return lhs === rhs
-}
-
-@warn_unused_result
-public func ~= (lhs: ListMonitor, rhs: ListMonitor) -> Bool {
-    
-    return lhs.fetchedResultsController === rhs.fetchedResultsController
-}
-
-extension ListMonitor: Equatable { }
-
-
 // MARK: - ListMonitor: FetchedResultsControllerHandler
 
 extension ListMonitor: FetchedResultsControllerHandler {
     
     // MARK: FetchedResultsControllerHandler
     
-    internal func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
+    internal func controller(_ controller: NSFetchedResultsController, didChangeObject anObject: Any, atIndexPath indexPath: IndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
         
         switch type {
             
-        case .Insert:
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                ListMonitorDidInsertObjectNotification,
+        case .insert:
+            NotificationCenter.default.post(
+                name: Notification.Name.listMonitorDidInsertObject,
                 object: self,
                 userInfo: [
-                    UserInfoKeyObject: anObject,
-                    UserInfoKeyNewIndexPath: newIndexPath!
+                    String(describing: NSManagedObject.self): anObject,
+                    "\(String(describing: IndexPath.self)).New": newIndexPath!
                 ]
             )
             
-        case .Delete:
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                ListMonitorDidDeleteObjectNotification,
+        case .delete:
+            NotificationCenter.default.post(
+                name: Notification.Name.listMonitorDidDeleteObject,
                 object: self,
                 userInfo: [
-                    UserInfoKeyObject: anObject,
-                    UserInfoKeyIndexPath: indexPath!
+                    String(describing: NSManagedObject.self): anObject,
+                    String(describing: IndexPath.self): indexPath!
                 ]
             )
             
-        case .Update:
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                ListMonitorDidUpdateObjectNotification,
+        case .update:
+            NotificationCenter.default.post(
+                name: Notification.Name.listMonitorDidUpdateObject,
                 object: self,
                 userInfo: [
-                    UserInfoKeyObject: anObject,
-                    UserInfoKeyIndexPath: indexPath!
+                    String(describing: NSManagedObject.self): anObject,
+                    String(describing: IndexPath.self): indexPath!
                 ]
             )
             
-        case .Move:
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                ListMonitorDidMoveObjectNotification,
+        case .move:
+            NotificationCenter.default.post(
+                name: Notification.Name.listMonitorDidMoveObject,
                 object: self,
                 userInfo: [
-                    UserInfoKeyObject: anObject,
-                    UserInfoKeyIndexPath: indexPath!,
-                    UserInfoKeyNewIndexPath: newIndexPath!
+                    String(describing: NSManagedObject.self): anObject,
+                    String(describing: IndexPath.self): indexPath!,
+                    "\(String(describing: IndexPath.self)).New": newIndexPath!
                 ]
             )
         }
     }
     
-    internal func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
+    internal func controller(_ controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
         
         switch type {
             
-        case .Insert:
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                ListMonitorDidInsertSectionNotification,
+        case .insert:
+            NotificationCenter.default.post(
+                name: Notification.Name.listMonitorDidInsertSection,
                 object: self,
                 userInfo: [
-                    UserInfoKeySectionInfo: sectionInfo,
-                    UserInfoKeySectionIndex: NSNumber(integer: sectionIndex)
+                    String(describing: NSFetchedResultsSectionInfo.self): sectionInfo,
+                    String(describing: NSNumber.self): NSNumber(value: sectionIndex)
                 ]
             )
             
-        case .Delete:
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                ListMonitorDidDeleteSectionNotification,
+        case .delete:
+            NotificationCenter.default.post(
+                name: Notification.Name.listMonitorDidDeleteSection,
                 object: self,
                 userInfo: [
-                    UserInfoKeySectionInfo: sectionInfo,
-                    UserInfoKeySectionIndex: NSNumber(integer: sectionIndex)
+                    String(describing: NSFetchedResultsSectionInfo.self): sectionInfo,
+                    String(describing: NSNumber.self): NSNumber(value: sectionIndex)
                 ]
             )
             
@@ -1289,51 +1228,45 @@ extension ListMonitor: FetchedResultsControllerHandler {
         }
     }
     
-    internal func controllerWillChangeContent(controller: NSFetchedResultsController) {
+    internal func controllerWillChangeContent(_ controller: NSFetchedResultsController) {
         
         self.taskGroup.enter()
-        NSNotificationCenter.defaultCenter().postNotificationName(
-            ListMonitorWillChangeListNotification,
+        NotificationCenter.default.post(
+            name: Notification.Name.listMonitorWillChangeList,
             object: self
         )
     }
     
-   internal func controllerDidChangeContent(controller: NSFetchedResultsController) {
+   internal func controllerDidChangeContent(_ controller: NSFetchedResultsController) {
         
-        NSNotificationCenter.defaultCenter().postNotificationName(
-            ListMonitorDidChangeListNotification,
+        NotificationCenter.default.post(
+            name: Notification.Name.listMonitorDidChangeList,
             object: self
         )
         self.taskGroup.leave()
     }
     
-   internal func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String? {
+   internal func controller(_ controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String? {
     
-        return self.sectionIndexTransformer(sectionName: sectionName)
+        return self.sectionIndexTransformer(sectionName)
     }
 }
 
 
 // MARK: - Notification Keys
-
-private let ListMonitorWillChangeListNotification = "ListMonitorWillChangeListNotification"
-private let ListMonitorDidChangeListNotification = "ListMonitorDidChangeListNotification"
-private let ListMonitorWillRefetchListNotification = "ListMonitorWillRefetchListNotification"
-private let ListMonitorDidRefetchListNotification = "ListMonitorDidRefetchListNotification"
-
-private let ListMonitorDidInsertObjectNotification = "ListMonitorDidInsertObjectNotification"
-private let ListMonitorDidDeleteObjectNotification = "ListMonitorDidDeleteObjectNotification"
-private let ListMonitorDidUpdateObjectNotification = "ListMonitorDidUpdateObjectNotification"
-private let ListMonitorDidMoveObjectNotification = "ListMonitorDidMoveObjectNotification"
-
-private let ListMonitorDidInsertSectionNotification = "ListMonitorDidInsertSectionNotification"
-private let ListMonitorDidDeleteSectionNotification = "ListMonitorDidDeleteSectionNotification"
-
-private let UserInfoKeyObject = "UserInfoKeyObject"
-private let UserInfoKeyIndexPath = "UserInfoKeyIndexPath"
-private let UserInfoKeyNewIndexPath = "UserInfoKeyNewIndexPath"
-
-private let UserInfoKeySectionInfo = "UserInfoKeySectionInfo"
-private let UserInfoKeySectionIndex = "UserInfoKeySectionIndex"
+    
+fileprivate extension Notification.Name {
+    
+    fileprivate static let listMonitorWillChangeList = Notification.Name(rawValue: "listMonitorWillChangeList")
+    fileprivate static let listMonitorDidChangeList = Notification.Name(rawValue: "listMonitorDidChangeList")
+    fileprivate static let listMonitorWillRefetchList = Notification.Name(rawValue: "listMonitorWillRefetchList")
+    fileprivate static let listMonitorDidRefetchList = Notification.Name(rawValue: "listMonitorDidRefetchList")
+    fileprivate static let listMonitorDidInsertObject = Notification.Name(rawValue: "listMonitorDidInsertObject")
+    fileprivate static let listMonitorDidDeleteObject = Notification.Name(rawValue: "listMonitorDidDeleteObject")
+    fileprivate static let listMonitorDidUpdateObject = Notification.Name(rawValue: "listMonitorDidUpdateObject")
+    fileprivate static let listMonitorDidMoveObject = Notification.Name(rawValue: "listMonitorDidMoveObject")
+    fileprivate static let listMonitorDidInsertSection = Notification.Name(rawValue: "listMonitorDidInsertSection")
+    fileprivate static let listMonitorDidDeleteSection = Notification.Name(rawValue: "listMonitorDidDeleteSection")
+}
 
 #endif
diff --git a/Sources/Observing/ListObserver.swift b/Sources/Observing/ListObserver.swift
index 0e53402..17c7254 100644
--- a/Sources/Observing/ListObserver.swift
+++ b/Sources/Observing/ListObserver.swift
@@ -35,8 +35,8 @@ import CoreData
  Implement the `ListObserver` protocol to observe changes to a list of `NSManagedObject`s. `ListObserver`s may register themselves to a `ListMonitor`'s `addObserver(_:)` method:
  ```
  let monitor = CoreStore.monitorList(
-     From(MyPersonEntity),
-     OrderBy(.Ascending("lastName"))
+     From(),
+     OrderBy(.ascending("lastName"))
  )
  monitor.addObserver(self)
  ```
@@ -49,32 +49,37 @@ public protocol ListObserver: class {
     associatedtype ListEntityType: NSManagedObject
     
     /**
-     Handles processing just before a change to the observed list occurs
+     Handles processing just before a change to the observed list occurs. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ListMonitor` monitoring the list being observed
      */
-    func listMonitorWillChange(monitor: ListMonitor)
+    func listMonitorWillChange(_ monitor: ListMonitor)
     
     /**
-     Handles processing right after a change to the observed list occurs
+     Handles processing right after a change to the observed list occurs. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ListMonitor` monitoring the object being observed
      */
-    func listMonitorDidChange(monitor: ListMonitor)
+    func listMonitorDidChange(_ monitor: ListMonitor)
     
     /**
-     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.
+     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. (Optional)
+     The default implementation does nothing.
+     - Note: 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)
+    func listMonitorWillRefetch(_ monitor: ListMonitor)
     
     /**
-     After the `ListMonitor`'s `refetch(...)` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes.
+     After the `ListMonitor`'s `refetch(...)` method is called, this method is broadcast after the `NSFetchedResultsController`'s last `controllerDidChangeContent(_:)` notification completes. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ListMonitor` monitoring the object being observed
      */
-    func listMonitorDidRefetch(monitor: ListMonitor)
+    func listMonitorDidRefetch(_ monitor: ListMonitor)
 }
 
 
@@ -82,25 +87,13 @@ public protocol ListObserver: class {
 
 public extension ListObserver {
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitorWillChange(monitor: ListMonitor) { }
+    public func listMonitorWillChange(_ monitor: ListMonitor) { }
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitorDidChange(monitor: ListMonitor) { }
+    public func listMonitorDidChange(_ monitor: ListMonitor) { }
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitorWillRefetch(monitor: ListMonitor) { }
+    public func listMonitorWillRefetch(_ monitor: ListMonitor) { }
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitorDidRefetch(monitor: ListMonitor) { }
+    public func listMonitorDidRefetch(_ monitor: ListMonitor) { }
 }
 
 
@@ -110,8 +103,8 @@ public extension ListObserver {
  Implement the `ListObjectObserver` protocol to observe detailed changes to a list's object. `ListObjectObserver`s may register themselves to a `ListMonitor`'s `addObserver(_:)` method:
  ```
  let monitor = CoreStore.monitorList(
-     From(MyPersonEntity),
-     OrderBy(.Ascending("lastName"))
+     From(),
+     OrderBy(.ascending("lastName"))
  )
  monitor.addObserver(self)
  ```
@@ -119,41 +112,45 @@ public extension ListObserver {
 public protocol ListObjectObserver: ListObserver {
     
     /**
-     Notifies that an object was inserted to the specified `NSIndexPath` in the list
+     Notifies that an object was inserted to the specified `NSIndexPath` in the list. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ListMonitor` monitoring the list being observed
      - parameter object: the entity type for the inserted object
      - parameter indexPath: the new `NSIndexPath` for the inserted object
      */
-    func listMonitor(monitor: ListMonitor, didInsertObject object: ListEntityType, toIndexPath indexPath: NSIndexPath)
+    func listMonitor(_ monitor: ListMonitor, didInsertObject object: ListEntityType, toIndexPath indexPath: IndexPath)
     
     /**
-     Notifies that an object was deleted from the specified `NSIndexPath` in the list
+     Notifies that an object was deleted from the specified `NSIndexPath` in the list. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ListMonitor` monitoring the list being observed
      - parameter object: the entity type for the deleted object
      - parameter indexPath: the `NSIndexPath` for the deleted object
      */
-    func listMonitor(monitor: ListMonitor, didDeleteObject object: ListEntityType, fromIndexPath indexPath: NSIndexPath)
+    func listMonitor(_ monitor: ListMonitor, didDeleteObject object: ListEntityType, fromIndexPath indexPath: IndexPath)
     
     /**
-     Notifies that an object at the specified `NSIndexPath` was updated
+     Notifies that an object at the specified `NSIndexPath` was updated. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ListMonitor` monitoring the list being observed
      - parameter object: the entity type for the updated object
      - parameter indexPath: the `NSIndexPath` for the updated object
      */
-    func listMonitor(monitor: ListMonitor, didUpdateObject object: ListEntityType, atIndexPath indexPath: NSIndexPath)
+    func listMonitor(_ monitor: ListMonitor, didUpdateObject object: ListEntityType, atIndexPath indexPath: IndexPath)
     
     /**
-     Notifies that an object's index changed
+     Notifies that an object's index changed. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ListMonitor` monitoring the list being observed
      - parameter object: the entity type for the moved object
      - parameter fromIndexPath: the previous `NSIndexPath` for the moved object
      - parameter toIndexPath: the new `NSIndexPath` for the moved object
      */
-    func listMonitor(monitor: ListMonitor, didMoveObject object: ListEntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
+    func listMonitor(_ monitor: ListMonitor, didMoveObject object: ListEntityType, fromIndexPath: IndexPath, toIndexPath: IndexPath)
 }
 
 
@@ -161,25 +158,13 @@ public protocol ListObjectObserver: ListObserver {
 
 public extension ListObjectObserver {
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitor(monitor: ListMonitor, didInsertObject object: ListEntityType, toIndexPath indexPath: NSIndexPath) { }
+    public func listMonitor(_ monitor: ListMonitor, didInsertObject object: ListEntityType, toIndexPath indexPath: IndexPath) { }
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitor(monitor: ListMonitor, didDeleteObject object: ListEntityType, fromIndexPath indexPath: NSIndexPath) { }
+    public func listMonitor(_ monitor: ListMonitor, didDeleteObject object: ListEntityType, fromIndexPath indexPath: IndexPath) { }
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitor(monitor: ListMonitor, didUpdateObject object: ListEntityType, atIndexPath indexPath: NSIndexPath) { }
+    public func listMonitor(_ monitor: ListMonitor, didUpdateObject object: ListEntityType, atIndexPath indexPath: IndexPath) { }
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitor(monitor: ListMonitor, didMoveObject object: ListEntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) { }
+    public func listMonitor(_ monitor: ListMonitor, didMoveObject object: ListEntityType, fromIndexPath: IndexPath, toIndexPath: IndexPath) { }
 }
 
 
@@ -189,9 +174,9 @@ public extension ListObjectObserver {
  Implement the `ListSectionObserver` protocol to observe changes to a list's section info. `ListSectionObserver`s may register themselves to a `ListMonitor`'s `addObserver(_:)` method:
  ```
  let monitor = CoreStore.monitorSectionedList(
-     From(MyPersonEntity),
+     From(),
      SectionBy("age") { "Age \($0)" },
-     OrderBy(.Ascending("lastName"))
+     OrderBy(.ascending("lastName"))
  )
  monitor.addObserver(self)
  ```
@@ -199,22 +184,24 @@ public extension ListObjectObserver {
 public protocol ListSectionObserver: ListObjectObserver {
     
     /**
-     Notifies that a section was inserted at the specified index
+     Notifies that a section was inserted at the specified index. (Optional)
+     The default implementation does nothing.
      
      - 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, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
+    func listMonitor(_ monitor: ListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
     
     /**
-     Notifies that a section was inserted at the specified index
+     Notifies that a section was inserted at the specified index. (Optional)
+     The default implementation does nothing.
      
      - 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, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
+    func listMonitor(_ monitor: ListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
 }
 
 
@@ -222,15 +209,9 @@ public protocol ListSectionObserver: ListObjectObserver {
 
 public extension ListSectionObserver {
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitor(monitor: ListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { }
+    public func listMonitor(_ monitor: ListMonitor, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) { }
     
-    /**
-     The default implementation does nothing.
-     */
-    func listMonitor(monitor: ListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { }
+    public func listMonitor(_ monitor: ListMonitor, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) { }
 }
 
 #endif
diff --git a/Sources/Observing/ObjectMonitor.swift b/Sources/Observing/ObjectMonitor.swift
index e1e4ff3..5db3b32 100644
--- a/Sources/Observing/ObjectMonitor.swift
+++ b/Sources/Observing/ObjectMonitor.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 #if os(iOS) || os(watchOS) || os(tvOS)
@@ -44,14 +41,14 @@ import CoreData
  
  Observers registered via `addObserver(_:)` are not retained. `ObjectMonitor` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
  */
-public final class ObjectMonitor {
+public final class ObjectMonitor: Equatable {
     
     /**
      Returns the `NSManagedObject` instance being observed, or `nil` if the object was already deleted.
      */
-    public var object: T? {
+    public var object: EntityType? {
         
-        return self.fetchedResultsController.fetchedObjects?.first as? T
+        return self.fetchedResultsController.fetchedObjects?.first as? EntityType
     }
     
     /**
@@ -73,7 +70,7 @@ public final class ObjectMonitor {
      
      - parameter observer: an `ObjectObserver` to send change notifications to
      */
-    public func addObserver(observer: U) {
+    public func addObserver(_ observer: U) where U.ObjectEntityType == EntityType {
         
         self.unregisterObserver(observer)
         self.registerObserver(
@@ -100,12 +97,25 @@ public final class ObjectMonitor {
      
      - parameter observer: an `ObjectObserver` to unregister notifications to
      */
-    public func removeObserver(observer: U) {
+    public func removeObserver(_ observer: U) where U.ObjectEntityType == EntityType {
         
         self.unregisterObserver(observer)
     }
     
     
+    // MARK: Equatable
+    
+    public static func == (lhs: ObjectMonitor, rhs: ObjectMonitor) -> Bool {
+        
+        return lhs === rhs
+    }
+    
+    public static func ~= (lhs: ObjectMonitor, rhs: ObjectMonitor) -> Bool {
+        
+        return lhs === rhs
+    }
+    
+    
     // MARK: Hashable
     
     public var hashValue: Int {
@@ -116,25 +126,25 @@ public final class ObjectMonitor {
     
     // MARK: Internal
     
-    internal convenience init(dataStack: DataStack, object: T) {
+    internal convenience init(dataStack: DataStack, object: EntityType) {
         
         self.init(context: dataStack.mainContext, object: object)
     }
     
-    internal convenience init(unsafeTransaction: UnsafeDataTransaction, object: T) {
+    internal convenience init(unsafeTransaction: UnsafeDataTransaction, object: EntityType) {
         
         self.init(context: unsafeTransaction.context, object: object)
     }
     
-    internal func registerObserver(observer: U, willChangeObject: (observer: U, monitor: ObjectMonitor, object: T) -> Void, didDeleteObject: (observer: U, monitor: ObjectMonitor, object: T) -> Void, didUpdateObject: (observer: U, monitor: ObjectMonitor, object: T, changedPersistentKeys: Set) -> Void) {
+    internal func registerObserver(_ observer: U, willChangeObject: @escaping (_ observer: U, _ monitor: ObjectMonitor, _ object: EntityType) -> Void, didDeleteObject: @escaping (_ observer: U, _ monitor: ObjectMonitor, _ object: EntityType) -> Void, didUpdateObject: @escaping (_ observer: U, _ monitor: ObjectMonitor, _ object: EntityType, _ changedPersistentKeys: Set) -> Void) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
-            "Attempted to add an observer of type \(cs_typeName(observer)) outside the main thread."
+            Thread.isMainThread,
+            "Attempted to add an observer of type \(cs_typeName(observer as AnyObject)) outside the main thread."
         )
         self.registerChangeNotification(
             &self.willChangeObjectKey,
-            name: ObjectMonitorWillChangeObjectNotification,
+            name: Notification.Name.objectMonitorWillChangeObject,
             toObserver: observer,
             callback: { [weak observer] (monitor) -> Void in
                 
@@ -142,12 +152,12 @@ public final class ObjectMonitor {
                     
                     return
                 }
-                willChangeObject(observer: observer, monitor: monitor, object: object)
+                willChangeObject(observer, monitor, object)
             }
         )
         self.registerObjectNotification(
             &self.didDeleteObjectKey,
-            name: ObjectMonitorDidDeleteObjectNotification,
+            name: Notification.Name.objectMonitorDidDeleteObject,
             toObserver: observer,
             callback: { [weak observer] (monitor, object) -> Void in
                 
@@ -155,12 +165,12 @@ public final class ObjectMonitor {
                     
                     return
                 }
-                didDeleteObject(observer: observer, monitor: monitor, object: object)
+                didDeleteObject(observer, monitor, object)
             }
         )
         self.registerObjectNotification(
             &self.didUpdateObjectKey,
-            name: ObjectMonitorDidUpdateObjectNotification,
+            name: Notification.Name.objectMonitorDidUpdateObject,
             toObserver: observer,
             callback: { [weak self, weak observer] (monitor, object) -> Void in
                 
@@ -170,7 +180,7 @@ public final class ObjectMonitor {
                 }
                 
                 let previousCommitedAttributes = self.lastCommittedAttributes
-                let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [String: NSObject]
+                let currentCommitedAttributes = object.committedValues(forKeys: nil) as! [String: NSObject]
                 
                 var changedKeys = Set()
                 for key in currentCommitedAttributes.keys {
@@ -182,20 +192,15 @@ public final class ObjectMonitor {
                 }
                 
                 self.lastCommittedAttributes = currentCommitedAttributes
-                didUpdateObject(
-                    observer: observer,
-                    monitor: monitor,
-                    object: object,
-                    changedPersistentKeys: changedKeys
-                )
+                didUpdateObject(observer, monitor, object, changedKeys)
             }
         )
     }
     
-    internal func unregisterObserver(observer: AnyObject) {
+    internal func unregisterObserver(_ observer: AnyObject) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to remove an observer of type \(cs_typeName(observer)) outside the main thread."
         )
         
@@ -207,7 +212,7 @@ public final class ObjectMonitor {
     
     internal func upcast() -> ObjectMonitor {
         
-        return unsafeBitCast(self, ObjectMonitor.self)
+        return unsafeBitCast(self, to: ObjectMonitor.self)
     }
     
     deinit {
@@ -219,19 +224,19 @@ public final class ObjectMonitor {
     // MARK: Private
     
     private let fetchedResultsController: CoreStoreFetchedResultsController
-    private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
+    private let fetchedResultsControllerDelegate: FetchedResultsControllerDelegate
     private var lastCommittedAttributes = [String: NSObject]()
     
     private var willChangeObjectKey: Void?
     private var didDeleteObjectKey: Void?
     private var didUpdateObjectKey: Void?
     
-    private init(context: NSManagedObjectContext, object: T) {
+    private init(context: NSManagedObjectContext, object: EntityType) {
         
         let fetchRequest = CoreStoreFetchRequest()
         fetchRequest.entity = object.entity
         fetchRequest.fetchLimit = 0
-        fetchRequest.resultType = .ManagedObjectResultType
+        fetchRequest.resultType = .managedObjectResultType
         fetchRequest.sortDescriptors = []
         fetchRequest.includesPendingChanges = false
         fetchRequest.shouldRefreshRefetchedObjects = true
@@ -239,11 +244,11 @@ public final class ObjectMonitor {
         let objectID = object.objectID
         let fetchedResultsController = CoreStoreFetchedResultsController(
             context: context,
-            fetchRequest: fetchRequest,
+            fetchRequest: fetchRequest.dynamicCast(),
             applyFetchClauses: Where("SELF", isEqualTo: objectID).applyToFetchRequest
         )
         
-        let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate()
+        let fetchedResultsControllerDelegate = FetchedResultsControllerDelegate()
         
         self.fetchedResultsController = fetchedResultsController
         self.fetchedResultsControllerDelegate = fetchedResultsControllerDelegate
@@ -252,10 +257,10 @@ public final class ObjectMonitor {
         fetchedResultsControllerDelegate.fetchedResultsController = fetchedResultsController
         try! fetchedResultsController.performFetchFromSpecifiedStores()
         
-        self.lastCommittedAttributes = (self.object?.committedValuesForKeys(nil) as? [String: NSObject]) ?? [:]
+        self.lastCommittedAttributes = (self.object?.committedValues(forKeys: nil) as? [String: NSObject]) ?? [:]
     }
     
-    private func registerChangeNotification(notificationKey: UnsafePointer, name: String, toObserver observer: AnyObject, callback: (monitor: ObjectMonitor) -> Void) {
+    private func registerChangeNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ObjectMonitor) -> Void) {
         
         cs_setAssociatedRetainedObject(
             NotificationObserver(
@@ -267,7 +272,7 @@ public final class ObjectMonitor {
                         
                         return
                     }
-                    callback(monitor: self)
+                    callback(self)
                 }
             ),
             forKey: notificationKey,
@@ -275,7 +280,7 @@ public final class ObjectMonitor {
         )
     }
     
-    private func registerObjectNotification(notificationKey: UnsafePointer, name: String, toObserver observer: AnyObject, callback: (monitor: ObjectMonitor, object: T) -> Void) {
+    private func registerObjectNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: AnyObject, callback: @escaping (_ monitor: ObjectMonitor, _ object: EntityType) -> Void) {
         
         cs_setAssociatedRetainedObject(
             NotificationObserver(
@@ -285,11 +290,11 @@ public final class ObjectMonitor {
                     
                     guard let `self` = self,
                         let userInfo = note.userInfo,
-                        let object = userInfo[UserInfoKeyObject] as? T else {
+                        let object = userInfo[String(describing: NSManagedObject.self)] as? EntityType else {
                             
                             return
                     }
-                    callback(monitor: self, object: object)
+                    callback(self, object)
                 }
             ),
             forKey: notificationKey,
@@ -299,53 +304,39 @@ public final class ObjectMonitor {
 }
 
 
-// MARK: - ObjectMonitor: Equatable
-
-public func == (lhs: ObjectMonitor, rhs: ObjectMonitor) -> Bool {
-    
-    return lhs === rhs
-}
-
-public func ~= (lhs: ObjectMonitor, rhs: ObjectMonitor) -> Bool {
-    
-    return lhs === rhs
-}
-
-extension ObjectMonitor: Equatable { }
-
-
 // MARK: - ObjectMonitor: FetchedResultsControllerHandler
 
 extension ObjectMonitor: FetchedResultsControllerHandler {
     
     // MARK: FetchedResultsControllerHandler
     
-    internal func controllerWillChangeContent(controller: NSFetchedResultsController) {
+    internal func controllerWillChangeContent(_ controller: NSFetchedResultsController) {
         
-        NSNotificationCenter.defaultCenter().postNotificationName(
-            ObjectMonitorWillChangeObjectNotification,
+        NotificationCenter.default.post(
+            name: Notification.Name.objectMonitorWillChangeObject,
             object: self
         )
     }
     
-    internal func controllerDidChangeContent(controller: NSFetchedResultsController) { }
+    internal func controllerDidChangeContent(_ controller: NSFetchedResultsController) { }
     
-    internal func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
+    internal func controller(_ controller: NSFetchedResultsController, didChangeObject anObject: Any, atIndexPath indexPath: IndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
         
         switch type {
             
-        case .Delete:
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                ObjectMonitorDidDeleteObjectNotification,
+        case .delete:
+            NotificationCenter.default.post(
+                name: Notification.Name.objectMonitorDidDeleteObject,
                 object: self,
-                userInfo: [UserInfoKeyObject: anObject]
+                userInfo: [String(describing: NSManagedObject.self): anObject]
             )
             
-        case .Update:
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                ObjectMonitorDidUpdateObjectNotification,
+        case .update,
+             .move where indexPath == newIndexPath:
+            NotificationCenter.default.post(
+                name: Notification.Name.objectMonitorDidUpdateObject,
                 object: self,
-                userInfo: [UserInfoKeyObject: anObject]
+                userInfo: [String(describing: NSManagedObject.self): anObject]
             )
             
         default:
@@ -353,19 +344,22 @@ extension ObjectMonitor: FetchedResultsControllerHandler {
         }
     }
     
-    internal func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { }
+    internal func controller(_ controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { }
     
-    internal func controller(controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String? {
+    internal func controller(_ controller: NSFetchedResultsController, sectionIndexTitleForSectionName sectionName: String?) -> String? {
         
         return sectionName
     }
 }
+    
+    
+// MARK: - Notification.Name
 
-
-private let ObjectMonitorWillChangeObjectNotification = "ObjectMonitorWillChangeObjectNotification"
-private let ObjectMonitorDidDeleteObjectNotification = "ObjectMonitorDidDeleteObjectNotification"
-private let ObjectMonitorDidUpdateObjectNotification = "ObjectMonitorDidUpdateObjectNotification"
-
-private let UserInfoKeyObject = "UserInfoKeyObject"
+fileprivate extension Notification.Name {
+    
+    fileprivate static let objectMonitorWillChangeObject = Notification.Name(rawValue: "objectMonitorWillChangeObject")
+    fileprivate static let objectMonitorDidDeleteObject = Notification.Name(rawValue: "objectMonitorDidDeleteObject")
+    fileprivate static let objectMonitorDidUpdateObject = Notification.Name(rawValue: "objectMonitorDidUpdateObject")
+}
 
 #endif
diff --git a/Sources/Observing/ObjectObserver.swift b/Sources/Observing/ObjectObserver.swift
index f514ba4..b9fac1a 100644
--- a/Sources/Observing/ObjectObserver.swift
+++ b/Sources/Observing/ObjectObserver.swift
@@ -46,29 +46,32 @@ public protocol ObjectObserver: class {
     associatedtype ObjectEntityType: NSManagedObject
     
     /**
-     Handles processing just before a change to the observed `object` occurs
+     Handles processing just before a change to the observed `object` occurs. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ObjectMonitor` monitoring the object being observed
      - parameter object: the `NSManagedObject` instance being observed
      */
-    func objectMonitor(monitor: ObjectMonitor, willUpdateObject object: ObjectEntityType)
+    func objectMonitor(_ monitor: ObjectMonitor, willUpdateObject object: ObjectEntityType)
     
     /**
-     Handles processing right after a change to the observed `object` occurs
+     Handles processing right after a change to the observed `object` occurs. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ObjectMonitor` monitoring the object being observed
      - 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, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set)
+    func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set)
     
     /**
-     Handles processing right after `object` is deleted
+     Handles processing right after `object` is deleted. (Optional)
+     The default implementation does nothing.
      
      - parameter monitor: the `ObjectMonitor` monitoring the object being observed
      - parameter object: the `NSManagedObject` instance being observed
      */
-    func objectMonitor(monitor: ObjectMonitor, didDeleteObject object: ObjectEntityType)
+    func objectMonitor(_ monitor: ObjectMonitor, didDeleteObject object: ObjectEntityType)
 }
 
 
@@ -76,20 +79,11 @@ public protocol ObjectObserver: class {
 
 public extension ObjectObserver {
     
-    /**
-     The default implementation does nothing.
-     */
-    func objectMonitor(monitor: ObjectMonitor, willUpdateObject object: ObjectEntityType) { }
+    public func objectMonitor(_ monitor: ObjectMonitor, willUpdateObject object: ObjectEntityType) { }
     
-    /**
-     The default implementation does nothing.
-     */
-    func objectMonitor(monitor: ObjectMonitor, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set) { }
+    public func objectMonitor(_ monitor: ObjectMonitor, didUpdateObject object: ObjectEntityType, changedPersistentKeys: Set) { }
     
-    /**
-     The default implementation does nothing.
-     */
-    func objectMonitor(monitor: ObjectMonitor, didDeleteObject object: ObjectEntityType) { }
+    public func objectMonitor(_ monitor: ObjectMonitor, didDeleteObject object: ObjectEntityType) { }
 }
 
 #endif
diff --git a/Sources/Observing/SectionBy.swift b/Sources/Observing/SectionBy.swift
index e472fa3..63cfc9d 100644
--- a/Sources/Observing/SectionBy.swift
+++ b/Sources/Observing/SectionBy.swift
@@ -35,9 +35,9 @@ import CoreData
  The `SectionBy` clause indicates the key path to use to group the `ListMonitor` objects into sections. An optional closure can also be provided to transform the value into an appropriate section name:
  ```
  let monitor = CoreStore.monitorSectionedList(
-     From(MyPersonEntity),
+     From(),
      SectionBy("age") { "Age \($0)" },
-     OrderBy(.Ascending("lastName"))
+     OrderBy(.ascending("lastName"))
  )
  ```
  */
@@ -60,7 +60,7 @@ public struct SectionBy {
      - parameter sectionKeyPath: the key path to use to group the objects into sections
      - parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
      */
-    public init(_ sectionKeyPath: KeyPath, _ sectionIndexTransformer: (sectionName: String?) -> String?) {
+    public init(_ sectionKeyPath: KeyPath, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
         
         self.sectionKeyPath = sectionKeyPath
         self.sectionIndexTransformer = sectionIndexTransformer
@@ -70,7 +70,7 @@ public struct SectionBy {
     // MARK: Internal
     
     internal let sectionKeyPath: KeyPath
-    internal let sectionIndexTransformer: (sectionName: KeyPath?) -> String?
+    internal let sectionIndexTransformer: (_ sectionName: String?) -> String?
 }
 
 #endif
diff --git a/Sources/Observing/UnsafeDataTransaction+Observing.swift b/Sources/Observing/UnsafeDataTransaction+Observing.swift
index 86e80c6..723ad67 100644
--- a/Sources/Observing/UnsafeDataTransaction+Observing.swift
+++ b/Sources/Observing/UnsafeDataTransaction+Observing.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 #if os(iOS) || os(watchOS) || os(tvOS)
@@ -42,8 +39,7 @@ public extension UnsafeDataTransaction {
      - parameter object: the `NSManagedObject` to observe changes from
      - returns: a `ObjectMonitor` that monitors changes to `object`
      */
-    @warn_unused_result
-    public func monitorObject(object: T) -> ObjectMonitor {
+    public func monitorObject(_ object: T) -> ObjectMonitor {
         
         return ObjectMonitor(
             unsafeTransaction: self,
@@ -58,8 +54,7 @@ public extension UnsafeDataTransaction {
      - 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(from: From, _ fetchClauses: FetchClause...) -> ListMonitor {
+    public func monitorList(_ from: From, _ fetchClauses: FetchClause...) -> ListMonitor {
         
         return self.monitorList(from, fetchClauses)
     }
@@ -71,8 +66,7 @@ public extension UnsafeDataTransaction {
      - 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(from: From, _ fetchClauses: [FetchClause]) -> ListMonitor {
+    public func monitorList(_ from: From, _ fetchClauses: [FetchClause]) -> ListMonitor {
         
         CoreStore.assert(
             fetchClauses.filter { $0 is OrderBy }.count > 0,
@@ -97,7 +91,7 @@ public extension UnsafeDataTransaction {
      - parameter from: a `From` clause indicating the entity type
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      */
-    public func monitorList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) {
+    public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: FetchClause...) {
         
         self.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
     }
@@ -109,7 +103,7 @@ public extension UnsafeDataTransaction {
      - parameter from: a `From` clause indicating the entity type
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      */
-    public func monitorList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause])  {
+    public func monitorList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ fetchClauses: [FetchClause])  {
         
         CoreStore.assert(
             fetchClauses.filter { $0 is OrderBy }.count > 0,
@@ -136,8 +130,7 @@ public extension UnsafeDataTransaction {
      - 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(from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor {
+    public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor {
         
         return self.monitorSectionedList(from, sectionBy, fetchClauses)
     }
@@ -150,8 +143,7 @@ public extension UnsafeDataTransaction {
      - 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(from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor {
+    public func monitorSectionedList(_ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor {
         
         CoreStore.assert(
             fetchClauses.filter { $0 is OrderBy }.count > 0,
@@ -177,7 +169,7 @@ public extension UnsafeDataTransaction {
      - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      */
-    public func monitorSectionedList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
+    public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) {
         
         self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
     }
@@ -190,7 +182,7 @@ public extension UnsafeDataTransaction {
      - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
      - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
      */
-    public func monitorSectionedList(createAsynchronously createAsynchronously: (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
+    public func monitorSectionedList(createAsynchronously: @escaping (ListMonitor) -> Void, _ from: From, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) {
         
         CoreStore.assert(
             fetchClauses.filter { $0 is OrderBy }.count > 0,
diff --git a/Sources/Setup/CoreStore+Setup.swift b/Sources/Setup/CoreStore+Setup.swift
index 9201a96..d4346de 100644
--- a/Sources/Setup/CoreStore+Setup.swift
+++ b/Sources/Setup/CoreStore+Setup.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - CoreStore
@@ -53,9 +50,9 @@ public extension CoreStore {
     /**
      Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model.
      */
-    public static func entityDescriptionForType(type: NSManagedObject.Type) -> NSEntityDescription? {
+    public static func entityDescription(for type: NSManagedObject.Type) -> NSEntityDescription? {
         
-        return self.defaultStack.entityDescriptionForType(type)
+        return self.defaultStack.entityDescription(for: type)
     }
     
     /**
@@ -63,25 +60,25 @@ public extension CoreStore {
      ```
      try CoreStore.addStorageAndWait()
      ```
-     
      - returns: the local SQLite storage added to the `defaultStack`
      */
+    @discardableResult
     public static func addStorageAndWait() throws -> SQLiteStore {
         
-        return try self.defaultStack.addStorageAndWait(SQLiteStore)
+        return try self.defaultStack.addStorageAndWait(SQLiteStore.self)
     }
     
     /**
      Creates a `StorageInterface` of the specified store type with default values and adds it to the `defaultStack`. This method blocks until completion.
      ```
-     try CoreStore.addStorageAndWait(InMemoryStore)
+     try CoreStore.addStorageAndWait(InMemoryStore.self)
      ```
-     
      - parameter storeType: the `StorageInterface` type
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the `StorageInterface` added to the `defaultStack`
      */
-    public static func addStorageAndWait(storeType: T.Type) throws -> T {
+    @discardableResult
+    public static func addStorageAndWait(_ storeType: T.Type) throws -> T where T: DefaultInitializableStore {
         
         return try self.defaultStack.addStorageAndWait(storeType.init())
     }
@@ -91,27 +88,27 @@ public extension CoreStore {
      ```
      try CoreStore.addStorageAndWait(InMemoryStore(configuration: "Config1"))
      ```
-     
      - parameter storage: the `StorageInterface`
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the `StorageInterface` added to the `defaultStack`
      */
-    public static func addStorageAndWait(storage: T) throws -> T {
+    @discardableResult
+    public static func addStorageAndWait(_ storage: T) throws -> T {
         
         return try self.defaultStack.addStorageAndWait(storage)
     }
     
     /**
-     Creates a `LocalStorageface` of the specified store type with default values and adds it to the `defaultStack`. This method blocks until completion.
+     Creates a `LocalStorageInterface` of the specified store type with default values and adds it to the `defaultStack`. This method blocks until completion.
      ```
-     try CoreStore.addStorageAndWait(SQLiteStore)
+     try CoreStore.addStorageAndWait(SQLiteStore.self)
      ```
-     
-     - parameter storeType: the `LocalStorageface` type
+     - parameter storeType: the `LocalStorageInterface` type
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the local storage added to the `defaultStack`
      */
-    public static func addStorageAndWait(storageType: T.Type) throws -> T {
+    @discardableResult
+    public static func addStorageAndWait(_ storageType: T.Type) throws -> T where T: DefaultInitializableStore {
         
         return try self.defaultStack.addStorageAndWait(storageType.init())
     }
@@ -121,12 +118,12 @@ public extension CoreStore {
      ```
      try CoreStore.addStorageAndWait(SQLiteStore(configuration: "Config1"))
      ```
-     
      - parameter storage: the local storage
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the local storage added to the `defaultStack`. Note that this may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
      */
-    public static func addStorageAndWait(storage: T) throws -> T {
+    @discardableResult
+    public static func addStorageAndWait(_ storage: T) throws -> T {
         
         return try self.defaultStack.addStorageAndWait(storage)
     }
@@ -140,19 +137,19 @@ public extension CoreStore {
          ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
          ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
          configuration: "Config1",
-         cloudStorageOptions: .RecreateLocalStoreOnModelMismatch
+         cloudStorageOptions: .recreateLocalStoreOnModelMismatch
      ) else {
          // iCloud is not available on the device
          return
      }
      try CoreStore.addStorageAndWait(storage)
      ```
-     
      - parameter storage: the local storage
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the cloud storage added to the stack. Note that this may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
      */
-    public static func addStorageAndWait(storage: T) throws -> T {
+    @discardableResult
+    public static func addStorageAndWait(_ storage: T) throws -> T {
         
         return try self.defaultStack.addStorageAndWait(storage)
     }
@@ -161,60 +158,11 @@ public extension CoreStore {
     // MARK: Deprecated
     
     /**
-     Deprecated. Use `addStorageAndWait(_:)` by passing a `InMemoryStore` instance.
-     ```
-     try CoreStore.addStorage(InMemoryStore(configuration: configuration))
-     ```
+     Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model.
      */
-    @available(*, deprecated=2.0.0, obsoleted=2.0.0, message="Use addStorageAndWait(_:) by passing an InMemoryStore instance.")
-    public static func addInMemoryStoreAndWait(configuration configuration: String? = nil) throws -> NSPersistentStore {
+    @available(*, deprecated: 3.0.0, renamed: "entityDescription(for:)")
+    public static func entityDescriptionForType(_ type: NSManagedObject.Type) -> NSEntityDescription? {
         
-        return try self.defaultStack.addInMemoryStoreAndWait(configuration: configuration)
-    }
-    
-    /**
-     Deprecated. Use `addStorageAndWait(_:)` by passing a `LegacySQLiteStore` instance.
-     ```
-     try CoreStore.addStorage(
-         LegacySQLiteStore(
-             fileName: fileName,
-             configuration: configuration,
-             localStorageOptions: .RecreateStoreOnModelMismatch
-         )
-     )
-     ```
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use addStorageAndWait(_:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public static func addSQLiteStoreAndWait(fileName fileName: String, configuration: String? = nil, resetStoreOnModelMismatch: Bool = false) throws -> NSPersistentStore {
-        
-        return try self.defaultStack.addSQLiteStoreAndWait(
-            fileName: fileName,
-            configuration: configuration,
-            resetStoreOnModelMismatch: resetStoreOnModelMismatch
-        )
-    }
-    
-    /**
-     Deprecated. Use `addStorageAndWait(_:)` by passing a `LegacySQLiteStore` instance.
-     ```
-     try CoreStore.addStorage(
-         LegacySQLiteStore(
-             fileURL: fileURL,
-             configuration: configuration,
-             localStorageOptions: .RecreateStoreOnModelMismatch
-         )
-     )
-     ```
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use addStorageAndWait(_:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public static func addSQLiteStoreAndWait(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, resetStoreOnModelMismatch: Bool = false) throws -> NSPersistentStore {
-        
-        return try self.defaultStack.addSQLiteStoreAndWait(
-            fileURL: fileURL,
-            configuration: configuration,
-            resetStoreOnModelMismatch: resetStoreOnModelMismatch
-        )
+        return self.entityDescription(for: type)
     }
 }
diff --git a/Sources/Setup/DataStack.swift b/Sources/Setup/DataStack.swift
index 99e2b17..8463c43 100644
--- a/Sources/Setup/DataStack.swift
+++ b/Sources/Setup/DataStack.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - DataStack
@@ -35,7 +32,7 @@ import CoreData
 /**
  The `DataStack` encapsulates the data model for the Core Data stack. Each `DataStack` can have multiple data stores, usually specified as a "Configuration" in the model editor. Behind the scenes, the DataStack manages its own `NSPersistentStoreCoordinator`, a root `NSManagedObjectContext` for disk saves, and a shared `NSManagedObjectContext` designed as a read-only model interface for `NSManagedObjects`.
  */
-public final class DataStack {
+public final class DataStack: Equatable {
     
     /**
      Initializes a `DataStack` from the model with the specified `modelName` in the specified `bundle`.
@@ -44,7 +41,7 @@ public final class DataStack {
      - parameter bundle: an optional bundle to load models from. If not specified, the main bundle will be used.
      - parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
      */
-    public convenience init(modelName: String = DataStack.applicationName, bundle: NSBundle = NSBundle.mainBundle(), migrationChain: MigrationChain = nil) {
+    public convenience init(modelName: String = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
         
         let model = NSManagedObjectModel.fromBundle(
             bundle,
@@ -64,7 +61,7 @@ public final class DataStack {
         
         CoreStore.assert(
             migrationChain.valid,
-            "Invalid migration chain passed to the \(cs_typeName(DataStack)). Check that the model versions' order is correct and that no repetitions or ambiguities exist."
+            "Invalid migration chain passed to the \(cs_typeName(DataStack.self)). Check that the model versions' order is correct and that no repetitions or ambiguities exist."
         )
         
         self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
@@ -74,6 +71,8 @@ public final class DataStack {
         self.migrationChain = migrationChain
         
         self.rootSavingContext.parentStack = self
+        
+        self.mainContext.isDataStackContext = true
     }
     
     /**
@@ -95,20 +94,20 @@ public final class DataStack {
     /**
      Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass.
      */
-    public func entityDescriptionForType(type: NSManagedObject.Type) -> NSEntityDescription? {
+    public func entityDescription(for type: NSManagedObject.Type) -> NSEntityDescription? {
         
-        return NSEntityDescription.entityForName(
-            self.model.entityNameForClass(type),
-            inManagedObjectContext: self.mainContext
+        return NSEntityDescription.entity(
+            forEntityName: self.model.entityNameForClass(type),
+            in: self.mainContext
         )
     }
     
     /**
      Returns the `NSManagedObjectID` for the specified object URI if it exists in the persistent store.
      */
-    public func objectIDForURIRepresentation(url: NSURL) -> NSManagedObjectID? {
+    public func objectID(forURIRepresentation url: URL) -> NSManagedObjectID? {
         
-        return self.coordinator.managedObjectIDForURIRepresentation(url)
+        return self.coordinator.managedObjectID(forURIRepresentation: url)
     }
     
     /**
@@ -116,26 +115,26 @@ public final class DataStack {
      ```
      try dataStack.addStorageAndWait()
      ```
-     
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the local SQLite storage added to the stack
      */
+    @discardableResult
     public func addStorageAndWait() throws -> SQLiteStore {
         
-        return try self.addStorageAndWait(SQLiteStore)
+        return try self.addStorageAndWait(SQLiteStore.self)
     }
     
     /**
      Creates a `StorageInterface` of the specified store type with default values and adds it to the stack. This method blocks until completion.
      ```
-     try dataStack.addStorageAndWait(InMemoryStore)
+     try dataStack.addStorageAndWait(InMemoryStore.self)
      ```
-     
      - parameter storeType: the `StorageInterface` type
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the `StorageInterface` added to the stack
      */
-    public func addStorageAndWait(storeType: T.Type) throws -> T {
+    @discardableResult
+    public func addStorageAndWait(_ storeType: T.Type) throws -> T where T: DefaultInitializableStore {
         
         return try self.addStorageAndWait(storeType.init())
     }
@@ -145,12 +144,12 @@ public final class DataStack {
      ```
      try dataStack.addStorageAndWait(InMemoryStore(configuration: "Config1"))
      ```
-     
      - parameter storage: the `StorageInterface`
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the `StorageInterface` added to the stack
      */
-    public func addStorageAndWait(storage: T) throws -> T {
+    @discardableResult
+    public func addStorageAndWait(_ storage: T) throws -> T {
         
         do {
             
@@ -160,8 +159,7 @@ public final class DataStack {
                     
                     return storage
                 }
-                
-                try self.createPersistentStoreFromStorage(
+                _ = try self.createPersistentStoreFromStorage(
                     storage,
                     finalURL: nil,
                     finalStoreOptions: storage.storeOptions
@@ -181,16 +179,16 @@ public final class DataStack {
     }
     
     /**
-     Creates a `LocalStorageface` of the specified store type with default values and adds it to the stack. This method blocks until completion.
+     Creates a `LocalStorageInterface` of the specified store type with default values and adds it to the stack. This method blocks until completion.
      ```
-     try dataStack.addStorageAndWait(SQLiteStore)
+     try dataStack.addStorageAndWait(SQLiteStore.self)
      ```
-     
-     - parameter storeType: the `LocalStorageface` type
+     - parameter storeType: the `LocalStorageInterface` type
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the local storage added to the stack
      */
-    public func addStorageAndWait(storageType: T.Type) throws -> T {
+    @discardableResult
+    public func addStorageAndWait(_ storageType: T.Type) throws -> T where T: DefaultInitializableStore {
         
         return try self.addStorageAndWait(storageType.init())
     }
@@ -200,18 +198,18 @@ public final class DataStack {
      ```
      try dataStack.addStorageAndWait(SQLiteStore(configuration: "Config1"))
      ```
-     
      - parameter storage: the local storage
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the local storage added to the stack. Note that this may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
      */
-    public func addStorageAndWait(storage: T) throws -> T {
+    @discardableResult
+    public func addStorageAndWait(_ storage: T) throws -> T {
         
         return try self.coordinator.performSynchronously {
             
             let fileURL = storage.fileURL
             CoreStore.assert(
-                fileURL.fileURL,
+                fileURL.isFileURL,
                 "The specified store URL for the \"\(cs_typeName(storage))\" is invalid: \"\(fileURL)\""
             )
             
@@ -220,18 +218,18 @@ public final class DataStack {
                 return storage
             }
             
-            if let persistentStore = self.coordinator.persistentStoreForURL(fileURL) {
+            if let persistentStore = self.coordinator.persistentStore(for: fileURL as URL) {
                 
-                if let existingStorage = persistentStore.storageInterface as? T
-                    where storage.matchesPersistentStore(persistentStore) {
+                if let existingStorage = persistentStore.storageInterface as? T,
+                    storage.matchesPersistentStore(persistentStore) {
                     
                     return existingStorage
                 }
                 
-                let error = CoreStoreError.DifferentStorageExistsAtURL(existingPersistentStoreURL: fileURL)
+                let error = CoreStoreError.differentStorageExistsAtURL(existingPersistentStoreURL: fileURL)
                 CoreStore.log(
                     error,
-                    "Failed to add \(cs_typeName(storage)) at \"\(fileURL)\" because a different \(cs_typeName(NSPersistentStore)) at that URL already exists."
+                    "Failed to add \(cs_typeName(storage)) at \"\(fileURL)\" because a different \(cs_typeName(NSPersistentStore.self)) at that URL already exists."
                 )
                 throw error
             }
@@ -239,36 +237,39 @@ public final class DataStack {
             do {
                 
                 var localStorageOptions = storage.localStorageOptions
-                localStorageOptions.remove(.RecreateStoreOnModelMismatch)
+                localStorageOptions.remove(.recreateStoreOnModelMismatch)
                 
-                let storeOptions = storage.storeOptionsForOptions(localStorageOptions)
+                let storeOptions = storage.dictionary(forOptions: localStorageOptions)
                 do {
                     
-                    try NSFileManager.defaultManager().createDirectoryAtURL(
-                        fileURL.URLByDeletingLastPathComponent!,
+                    try FileManager.default.createDirectory(
+                        at: fileURL.deletingLastPathComponent(),
                         withIntermediateDirectories: true,
                         attributes: nil
                     )
-                    try self.createPersistentStoreFromStorage(
+                    _ = try self.createPersistentStoreFromStorage(
                         storage,
                         finalURL: fileURL,
                         finalStoreOptions: storeOptions
                     )
                     return storage
                 }
-                catch let error as NSError where storage.localStorageOptions.contains(.RecreateStoreOnModelMismatch) && error.isCoreDataMigrationError {
+                catch let error as NSError where storage.localStorageOptions.contains(.recreateStoreOnModelMismatch) && error.isCoreDataMigrationError {
                     
-                    let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(
-                        storage.dynamicType.storeType,
-                        URL: fileURL,
+                    let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
+                        ofType: type(of: storage).storeType,
+                        at: fileURL,
                         options: storeOptions
                     )
-                    _ = try storage.eraseStorageAndWait(soureModel: self.model[metadata])
-                    
-                    try self.createPersistentStoreFromStorage(
+                    try storage.eraseStorageAndWait(
+                        metadata: metadata,
+                        soureModelHint: self.model[metadata]
+                    )
+                    let finalStoreOptions = storage.dictionary(forOptions: storage.localStorageOptions)
+                    _ = try self.createPersistentStoreFromStorage(
                         storage,
                         finalURL: fileURL,
-                        finalStoreOptions: storeOptions
+                        finalStoreOptions: finalStoreOptions
                     )
                     return storage
                 }
@@ -294,19 +295,19 @@ public final class DataStack {
          ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
          ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
          configuration: "Config1",
-         cloudStorageOptions: .RecreateLocalStoreOnModelMismatch
+         cloudStorageOptions: .recreateLocalStoreOnModelMismatch
      ) else {
          // iCloud is not available on the device
          return
      }
      try dataStack.addStorageAndWait(storage)
      ```
-     
      - parameter storage: the local storage
      - throws: a `CoreStoreError` value indicating the failure
      - returns: the cloud storage added to the stack. Note that this may not always be the same instance as the parameter argument if a previous `CloudStorage` was already added at the same URL and with the same configuration.
      */
-    public func addStorageAndWait(storage: T) throws -> T {
+    @discardableResult
+    public func addStorageAndWait(_ storage: T) throws -> T {
         
         return try self.coordinator.performSynchronously {
             
@@ -316,18 +317,18 @@ public final class DataStack {
             }
             
             let cacheFileURL = storage.cacheFileURL
-            if let persistentStore = self.coordinator.persistentStoreForURL(cacheFileURL) {
+            if let persistentStore = self.coordinator.persistentStore(for: cacheFileURL as URL) {
                 
-                if let existingStorage = persistentStore.storageInterface as? T
-                    where storage.matchesPersistentStore(persistentStore) {
+                if let existingStorage = persistentStore.storageInterface as? T,
+                    storage.matchesPersistentStore(persistentStore) {
                     
                     return existingStorage
                 }
                 
-                let error = CoreStoreError.DifferentStorageExistsAtURL(existingPersistentStoreURL: cacheFileURL)
+                let error = CoreStoreError.differentStorageExistsAtURL(existingPersistentStoreURL: cacheFileURL)
                 CoreStore.log(
                     error,
-                    "Failed to add \(cs_typeName(storage)) at \"\(cacheFileURL)\" because a different \(cs_typeName(NSPersistentStore)) at that URL already exists."
+                    "Failed to add \(cs_typeName(storage)) at \"\(cacheFileURL)\" because a different \(cs_typeName(NSPersistentStore.self)) at that URL already exists."
                 )
                 throw error
             }
@@ -335,36 +336,31 @@ public final class DataStack {
             do {
                 
                 var cloudStorageOptions = storage.cloudStorageOptions
-                cloudStorageOptions.remove(.RecreateLocalStoreOnModelMismatch)
+                cloudStorageOptions.remove(.recreateLocalStoreOnModelMismatch)
                 
-                let storeOptions = storage.storeOptionsForOptions(cloudStorageOptions)
+                let storeOptions = storage.dictionary(forOptions: cloudStorageOptions)
                 do {
                     
-                    try NSFileManager.defaultManager().createDirectoryAtURL(
-                        cacheFileURL.URLByDeletingLastPathComponent!,
-                        withIntermediateDirectories: true,
-                        attributes: nil
-                    )
-                    try self.createPersistentStoreFromStorage(
+                    _ = try self.createPersistentStoreFromStorage(
                         storage,
                         finalURL: cacheFileURL,
                         finalStoreOptions: storeOptions
                     )
                     return storage
                 }
-                catch let error as NSError where storage.cloudStorageOptions.contains(.RecreateLocalStoreOnModelMismatch) && error.isCoreDataMigrationError {
+                catch let error as NSError where storage.cloudStorageOptions.contains(.recreateLocalStoreOnModelMismatch) && error.isCoreDataMigrationError {
                     
-                    let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(
-                        storage.dynamicType.storeType,
-                        URL: cacheFileURL,
+                    let finalStoreOptions = storage.dictionary(forOptions: storage.cloudStorageOptions)
+                    let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
+                        ofType: type(of: storage).storeType,
+                        at: cacheFileURL,
                         options: storeOptions
                     )
-                    _ = try storage.eraseStorageAndWait(soureModel: self.model[metadata])
-                    
-                    try self.createPersistentStoreFromStorage(
+                    _ = try self.model[metadata].flatMap(storage.eraseStorageAndWait)
+                    _ = try self.createPersistentStoreFromStorage(
                         storage,
                         finalURL: cacheFileURL,
-                        finalStoreOptions: storeOptions
+                        finalStoreOptions: finalStoreOptions
                     )
                     return storage
                 }
@@ -382,53 +378,51 @@ public final class DataStack {
     }
     
     
+    // MARK: Equatable
+    
+    public static func == (lhs: DataStack, rhs: DataStack) -> Bool {
+        
+        return lhs === rhs
+    }
+    
+    
     // MARK: Internal
     
-    internal static let applicationName = (NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String) ?? "CoreData"
+    internal static let applicationName = (Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String) ?? "CoreData"
     
     internal let coordinator: NSPersistentStoreCoordinator
     internal let rootSavingContext: NSManagedObjectContext
     internal let mainContext: NSManagedObjectContext
     internal let model: NSManagedObjectModel
     internal let migrationChain: MigrationChain
-    internal let childTransactionQueue: GCDQueue = .createSerial("com.coreStore.dataStack.childTransactionQueue")
-    internal let storeMetadataUpdateQueue = GCDQueue.createConcurrent("com.coreStore.persistentStoreBarrierQueue")
-    internal let migrationQueue: NSOperationQueue = {
+    internal let childTransactionQueue = DispatchQueue.serial("com.coreStore.dataStack.childTransactionQueue")
+    internal let storeMetadataUpdateQueue = DispatchQueue.concurrent("com.coreStore.persistentStoreBarrierQueue")
+    internal let migrationQueue: OperationQueue = {
         
-        let migrationQueue = NSOperationQueue()
+        let migrationQueue = OperationQueue()
         migrationQueue.maxConcurrentOperationCount = 1
         migrationQueue.name = "com.coreStore.migrationOperationQueue"
-        #if USE_FRAMEWORKS
-            
-            migrationQueue.qualityOfService = .Utility
-            migrationQueue.underlyingQueue = dispatch_queue_create("com.coreStore.migrationQueue", DISPATCH_QUEUE_SERIAL)
-        #else
-            
-            if #available(iOS 8.0, *) {
-                
-                migrationQueue.qualityOfService = .Utility
-                migrationQueue.underlyingQueue = dispatch_queue_create("com.coreStore.migrationQueue", DISPATCH_QUEUE_SERIAL)
-            }
-        #endif
+        migrationQueue.qualityOfService = .utility
+        migrationQueue.underlyingQueue = DispatchQueue.serial("com.coreStore.migrationQueue", qos: .userInitiated)
         return migrationQueue
     }()
     
-    internal func persistentStoreForStorage(storage: StorageInterface) -> NSPersistentStore? {
+    internal func persistentStoreForStorage(_ storage: StorageInterface) -> NSPersistentStore? {
         
         return self.coordinator.persistentStores
             .filter { $0.storageInterface === storage }
             .first
     }
     
-    internal func entityNameForEntityClass(entityClass: AnyClass) -> String? {
+    internal func entityNameForEntityClass(_ entityClass: AnyClass) -> String? {
         
         return self.model.entityNameForClass(entityClass)
     }
     
-    internal func persistentStoresForEntityClass(entityClass: AnyClass) -> [NSPersistentStore]? {
+    internal func persistentStoresForEntityClass(_ entityClass: AnyClass) -> [NSPersistentStore]? {
         
         var returnValue: [NSPersistentStore]? = nil
-        self.storeMetadataUpdateQueue.barrierSync {
+        self.storeMetadataUpdateQueue.sync(flags: .barrier) {
             
             returnValue = self.entityConfigurationsMapping[NSStringFromClass(entityClass)]?.map {
                 
@@ -438,57 +432,54 @@ public final class DataStack {
         return returnValue
     }
     
-    internal func persistentStoreForEntityClass(entityClass: AnyClass, configuration: String?, inferStoreIfPossible: Bool) -> (store: NSPersistentStore?, isAmbiguous: Bool) {
+    internal func persistentStoreForEntityClass(_ entityClass: AnyClass, configuration: String?, inferStoreIfPossible: Bool) -> (store: NSPersistentStore?, isAmbiguous: Bool) {
         
-        var returnValue: (store: NSPersistentStore?, isAmbiguous: Bool) = (store: nil, isAmbiguous: false)
-        self.storeMetadataUpdateQueue.barrierSync {
+        return self.storeMetadataUpdateQueue.sync(flags: .barrier) { () -> (store: NSPersistentStore?, isAmbiguous: Bool) in
             
             let configurationsForEntity = self.entityConfigurationsMapping[NSStringFromClass(entityClass)] ?? []
             if let configuration = configuration {
                 
                 if configurationsForEntity.contains(configuration) {
                     
-                    returnValue = (store: self.configurationStoreMapping[configuration], isAmbiguous: false)
-                    return
+                    return (store: self.configurationStoreMapping[configuration], isAmbiguous: false)
                 }
                 else if !inferStoreIfPossible {
                     
-                    return
+                    return (store: nil, isAmbiguous: false)
                 }
             }
             
             switch configurationsForEntity.count {
                 
             case 0:
-                return
+                return (store: nil, isAmbiguous: false)
                 
             case 1 where inferStoreIfPossible:
-                returnValue = (store: self.configurationStoreMapping[configurationsForEntity.first!], isAmbiguous: false)
+                return (store: self.configurationStoreMapping[configurationsForEntity.first!], isAmbiguous: false)
                 
             default:
-                returnValue = (store: nil, isAmbiguous: true)
+                return (store: nil, isAmbiguous: true)
             }
         }
-        return returnValue
     }
     
-    internal func createPersistentStoreFromStorage(storage: StorageInterface, finalURL: NSURL?, finalStoreOptions: [String: AnyObject]?) throws -> NSPersistentStore {
+    internal func createPersistentStoreFromStorage(_ storage: StorageInterface, finalURL: URL?, finalStoreOptions: [AnyHashable: Any]?) throws -> NSPersistentStore {
         
-        let persistentStore = try self.coordinator.addPersistentStoreWithType(
-            storage.dynamicType.storeType,
-            configuration: storage.configuration,
-            URL: finalURL,
+        let persistentStore = try self.coordinator.addPersistentStore(
+            ofType: type(of: storage).storeType,
+            configurationName: storage.configuration,
+            at: finalURL,
             options: finalStoreOptions
         )
         persistentStore.storageInterface = storage
         
-        self.storeMetadataUpdateQueue.barrierAsync {
+        self.storeMetadataUpdateQueue.async(flags: .barrier) {
             
             let configurationName = persistentStore.configurationName
             self.configurationStoreMapping[configurationName] = persistentStore
-            for entityDescription in (self.coordinator.managedObjectModel.entitiesForConfiguration(configurationName) ?? []) {
+            for entityDescription in (self.coordinator.managedObjectModel.entities(forConfigurationName: configurationName) ?? []) {
                 
-                let managedObjectClassName = entityDescription.managedObjectClassName
+                let managedObjectClassName = entityDescription.managedObjectClassName!
                 CoreStore.assert(
                     NSClassFromString(managedObjectClassName) != nil,
                     "The class \(cs_typeName(managedObjectClassName)) for the entity \(cs_typeName(entityDescription.name)) does not exist. Check if the subclass type and module name are properly configured."
@@ -520,7 +511,7 @@ public final class DataStack {
                 
                 coordinator.persistentStores.forEach {
                     
-                    _ = try? coordinator.removePersistentStore($0)
+                    _ = try? coordinator.remove($0)
                 }
             }
         }
@@ -529,79 +520,15 @@ public final class DataStack {
     
     // MARK: Deprecated
     
-    /**
-     Deprecated. Use `addStorageAndWait(_:)` by passing a `InMemoryStore` instance.
-     ```
-     try dataStack.addStorage(InMemoryStore(configuration: configuration))
-     ```
-     */
-    @available(*, deprecated=2.0.0, message="Use addStorageAndWait(_:) by passing an InMemoryStore instance.")
-    public func addInMemoryStoreAndWait(configuration configuration: String? = nil) throws -> NSPersistentStore {
+    @available(*, deprecated: 3.0.0, renamed: "entityDescription(for:)")
+    public func entityDescriptionForType(_ type: NSManagedObject.Type) -> NSEntityDescription? {
         
-        let storage = try self.addStorageAndWait(InMemoryStore(configuration: configuration))
-        return self.persistentStoreForStorage(storage)!
+        return self.entityDescription(for: type)
     }
     
-    /**
-     Deprecated. Use `addStorageAndWait(_:)` by passing a `LegacySQLiteStore` instance.
-     ```
-     try dataStack.addStorage(
-         LegacySQLiteStore(
-             fileName: fileName,
-             configuration: configuration,
-             localStorageOptions: .RecreateStoreOnModelMismatch
-         )
-     )
-     ```
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use addStorageAndWait(_:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public func addSQLiteStoreAndWait(fileName fileName: String, configuration: String? = nil, resetStoreOnModelMismatch: Bool = false) throws -> NSPersistentStore {
+    @available(*, deprecated: 3.0.0, renamed: "objectID(forURIRepresentation:)")
+    public func objectIDForURIRepresentation(_ url: URL) -> NSManagedObjectID? {
         
-        let storage = try self.addStorageAndWait(
-            LegacySQLiteStore(
-                fileName: fileName,
-                configuration: configuration,
-                localStorageOptions: resetStoreOnModelMismatch ? .RecreateStoreOnModelMismatch : .None
-            )
-        )
-        return self.persistentStoreForStorage(storage)!
-    }
-    
-    /**
-     Deprecated. Use `addStorageAndWait(_:)` by passing a `LegacySQLiteStore` instance.
-     ```
-     try dataStack.addStorage(
-         LegacySQLiteStore(
-             fileURL: fileURL,
-             configuration: configuration,
-             localStorageOptions: .RecreateStoreOnModelMismatch
-         )
-     )
-     ```
-     - Warning: The default SQLite file location for the `LegacySQLiteStore` and `SQLiteStore` are different. If the app was using this method prior to 2.0.0, make sure to use `LegacySQLiteStore`.
-     */
-    @available(*, deprecated=2.0.0, message="Use addStorageAndWait(_:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
-    public func addSQLiteStoreAndWait(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, resetStoreOnModelMismatch: Bool = false) throws -> NSPersistentStore {
-        
-        let storage = try self.addStorageAndWait(
-            LegacySQLiteStore(
-                fileURL: fileURL,
-                configuration: configuration,
-                localStorageOptions: resetStoreOnModelMismatch ? .RecreateStoreOnModelMismatch : .None
-            )
-        )
-        return self.persistentStoreForStorage(storage)!
+        return self.objectID(forURIRepresentation: url)
     }
 }
-
-
-// MARK: - DataStack: Equatable
-
-@warn_unused_result
-public func == (lhs: DataStack, rhs: DataStack) -> Bool {
-    
-    return lhs === rhs
-}
-
-extension DataStack: Equatable {}
diff --git a/Sources/Setup/StorageInterfaces/ICloudStore.swift b/Sources/Setup/StorageInterfaces/ICloudStore.swift
index c15c82b..a454a95 100644
--- a/Sources/Setup/StorageInterfaces/ICloudStore.swift
+++ b/Sources/Setup/StorageInterfaces/ICloudStore.swift
@@ -34,7 +34,7 @@ import CoreData
 /**
  A storage interface backed by an SQLite database managed by iCloud.
  */
-public class ICloudStore: CloudStorage {
+public final class ICloudStore: CloudStorage {
     
     /**
      Initializes an iCloud store interface from the given ubiquitous store information. Returns `nil` if the container could not be located or if iCloud storage is unavailable for the current user or device
@@ -45,7 +45,7 @@ public class ICloudStore: CloudStorage {
          ubiquitousContainerID: "iCloud.com.mycompany.myapp.containername",
          ubiquitousPeerToken: "9614d658014f4151a95d8048fb717cf0",
          configuration: "Config1",
-         cloudStorageOptions: .RecreateLocalStoreOnModelMismatch
+         cloudStorageOptions: .recreateLocalStoreOnModelMismatch
      ) else {
          // iCloud is not available on the device
          return
@@ -57,41 +57,41 @@ public class ICloudStore: CloudStorage {
          }
      )
      ```
-     
      - parameter ubiquitousContentName: the name of the store in iCloud. This is required and should not be empty, and should not contain periods (`.`).
-     - parameter ubiquitousContentTransactionLogsSubdirectory: an optional subdirectory path for the transaction logs
+     - parameter ubiquitousContentTransactionLogsSubdirectory: a required relative path for the transaction logs
      - parameter ubiquitousContainerID: a container if your app has multiple ubiquity container identifiers in its entitlements
      - parameter ubiquitousPeerToken: a per-application salt to allow multiple apps on the same device to share a Core Data store integrated with iCloud
      - parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `ubiquitousContentName` explicitly for each of them.
      - parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
      - parameter cloudStorageOptions: When the `ICloudStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
      */
-    public required init?(ubiquitousContentName: String, ubiquitousContentTransactionLogsSubdirectory: String? = nil, ubiquitousContainerID: String? = nil, ubiquitousPeerToken: String? = nil, configuration: String? = nil, cloudStorageOptions: CloudStorageOptions = nil) {
+    public required init?(ubiquitousContentName: String, ubiquitousContentTransactionLogsSubdirectory: String, ubiquitousContainerID: String? = nil, ubiquitousPeerToken: String? = nil, configuration: String? = nil, cloudStorageOptions: CloudStorageOptions = nil) {
         
         CoreStore.assert(
             !ubiquitousContentName.isEmpty,
             "The ubiquitousContentName cannot be empty."
         )
         CoreStore.assert(
-            !ubiquitousContentName.containsString("."),
+            !ubiquitousContentName.contains("."),
             "The ubiquitousContentName cannot contain periods."
         )
         CoreStore.assert(
-            ubiquitousContentTransactionLogsSubdirectory?.isEmpty != true,
-            "The ubiquitousContentURLRelativePath should not be empty if provided."
+            !ubiquitousContentTransactionLogsSubdirectory.isEmpty,
+            "The ubiquitousContentURLRelativePath should not be empty."
         )
         CoreStore.assert(
             ubiquitousPeerToken?.isEmpty != true,
             "The ubiquitousPeerToken should not be empty if provided."
         )
         
-        let fileManager = NSFileManager.defaultManager()
-        guard let cacheFileURL = fileManager.URLForUbiquityContainerIdentifier(ubiquitousContainerID) else {
+        let fileManager = FileManager.default
+        guard let cacheFolderURL = fileManager.url(forUbiquityContainerIdentifier: ubiquitousContainerID) else {
             
             return nil
         }
+        let cacheFileURL = cacheFolderURL.appendingPathComponent(ubiquitousContentTransactionLogsSubdirectory)
         
-        var storeOptions: [String: AnyObject] = [
+        var storeOptions: [String: Any] = [
             NSSQLitePragmasOption: ["journal_mode": "WAL"],
             NSPersistentStoreUbiquitousContentNameKey: ubiquitousContentName
         ]
@@ -110,10 +110,10 @@ public class ICloudStore: CloudStorage {
      
      - parameter observer: the observer to start sending ubiquitous notifications to
      */
-    public func addObserver(observer: T) {
+    public func addObserver(_ observer: T) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to add an observer of type \(cs_typeName(observer)) outside the main thread."
         )
         
@@ -121,7 +121,7 @@ public class ICloudStore: CloudStorage {
         
         self.registerNotification(
             &self.willFinishInitialImportKey,
-            name: ICloudUbiquitousStoreWillFinishInitialImportNotification,
+            name: Notification.Name.iCloudUbiquitousStoreWillFinishInitialImport,
             toObserver: observer,
             callback: { (observer, storage, dataStack) in
                 
@@ -130,7 +130,7 @@ public class ICloudStore: CloudStorage {
         )
         self.registerNotification(
             &self.didFinishInitialImportKey,
-            name: ICloudUbiquitousStoreDidFinishInitialImportNotification,
+            name: Notification.Name.iCloudUbiquitousStoreDidFinishInitialImport,
             toObserver: observer,
             callback: { (observer, storage, dataStack) in
                 
@@ -139,7 +139,7 @@ public class ICloudStore: CloudStorage {
         )
         self.registerNotification(
             &self.willAddAccountKey,
-            name: ICloudUbiquitousStoreWillAddAccountNotification,
+            name: Notification.Name.iCloudUbiquitousStoreWillAddAccount,
             toObserver: observer,
             callback: { (observer, storage, dataStack) in
                 
@@ -148,7 +148,7 @@ public class ICloudStore: CloudStorage {
         )
         self.registerNotification(
             &self.didAddAccountKey,
-            name: ICloudUbiquitousStoreDidAddAccountNotification,
+            name: Notification.Name.iCloudUbiquitousStoreDidAddAccount,
             toObserver: observer,
             callback: { (observer, storage, dataStack) in
                 
@@ -157,7 +157,7 @@ public class ICloudStore: CloudStorage {
         )
         self.registerNotification(
             &self.willRemoveAccountKey,
-            name: ICloudUbiquitousStoreWillRemoveAccountNotification,
+            name: Notification.Name.iCloudUbiquitousStoreWillRemoveAccount,
             toObserver: observer,
             callback: { (observer, storage, dataStack) in
                 
@@ -166,7 +166,7 @@ public class ICloudStore: CloudStorage {
         )
         self.registerNotification(
             &self.didRemoveAccountKey,
-            name: ICloudUbiquitousStoreDidRemoveAccountNotification,
+            name: Notification.Name.iCloudUbiquitousStoreDidRemoveAccount,
             toObserver: observer,
             callback: { (observer, storage, dataStack) in
                 
@@ -175,7 +175,7 @@ public class ICloudStore: CloudStorage {
         )
         self.registerNotification(
             &self.willRemoveContentKey,
-            name: ICloudUbiquitousStoreWillRemoveContentNotification,
+            name: Notification.Name.iCloudUbiquitousStoreWillRemoveContent,
             toObserver: observer,
             callback: { (observer, storage, dataStack) in
             
@@ -184,7 +184,7 @@ public class ICloudStore: CloudStorage {
         )
         self.registerNotification(
             &self.didRemoveContentKey,
-            name: ICloudUbiquitousStoreDidRemoveContentNotification,
+            name: Notification.Name.iCloudUbiquitousStoreDidRemoveContent,
             toObserver: observer,
             callback: { (observer, storage, dataStack) in
                 
@@ -198,10 +198,10 @@ public class ICloudStore: CloudStorage {
      
      - parameter observer: the observer to stop sending ubiquitous notifications to
      */
-    public func removeObserver(observer: ICloudStoreObserver) {
+    public func removeObserver(_ observer: ICloudStoreObserver) {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to remove an observer of type \(cs_typeName(observer)) outside the main thread."
         )
         let nilValue: AnyObject? = nil
@@ -266,12 +266,12 @@ public class ICloudStore: CloudStorage {
      [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
      ```
      */
-    public let storeOptions: [String: AnyObject]?
+    public let storeOptions: [AnyHashable: Any]?
     
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    public func didAddToDataStack(dataStack: DataStack) {
+    public func didAddToDataStack(_ dataStack: DataStack) {
         
         self.didRemoveFromDataStack(dataStack)
         
@@ -280,7 +280,7 @@ public class ICloudStore: CloudStorage {
         
         cs_setAssociatedRetainedObject(
             NotificationObserver(
-                notificationName: NSPersistentStoreCoordinatorStoresWillChangeNotification,
+                notificationName: Notification.Name.NSPersistentStoreCoordinatorStoresWillChange,
                 object: coordinator,
                 closure: { [weak self, weak dataStack] (note) -> Void in
                     
@@ -292,28 +292,28 @@ public class ICloudStore: CloudStorage {
                             return
                     }
                     
-                    let notification: String
-                    switch NSPersistentStoreUbiquitousTransitionType(rawValue: transitionType.unsignedIntegerValue) {
+                    let notification: Notification.Name
+                    switch NSPersistentStoreUbiquitousTransitionType(rawValue: transitionType.uintValue) {
                         
-                    case .InitialImportCompleted?:
-                        notification = ICloudUbiquitousStoreWillFinishInitialImportNotification
+                    case .initialImportCompleted?:
+                        notification = Notification.Name.iCloudUbiquitousStoreWillFinishInitialImport
                         
-                    case .AccountAdded?:
-                        notification = ICloudUbiquitousStoreWillAddAccountNotification
+                    case .accountAdded?:
+                        notification = Notification.Name.iCloudUbiquitousStoreWillAddAccount
                         
-                    case .AccountRemoved?:
-                        notification = ICloudUbiquitousStoreWillRemoveAccountNotification
+                    case .accountRemoved?:
+                        notification = Notification.Name.iCloudUbiquitousStoreWillRemoveAccount
                         
-                    case .ContentRemoved?:
-                        notification = ICloudUbiquitousStoreWillRemoveContentNotification
+                    case .contentRemoved?:
+                        notification = Notification.Name.iCloudUbiquitousStoreWillRemoveContent
                         
                     default:
                         return
                     }
-                    NSNotificationCenter.defaultCenter().postNotificationName(
-                        notification,
+                    NotificationCenter.default.post(
+                        name: notification,
                         object: self,
-                        userInfo: [UserInfoKeyDataStack: dataStack]
+                        userInfo: [String(describing: DataStack.self): dataStack]
                     )
                 }
             ),
@@ -322,7 +322,7 @@ public class ICloudStore: CloudStorage {
         )
         cs_setAssociatedRetainedObject(
             NotificationObserver(
-                notificationName: NSPersistentStoreCoordinatorStoresDidChangeNotification,
+                notificationName: NSNotification.Name.NSPersistentStoreCoordinatorStoresDidChange,
                 object: coordinator,
                 closure: { [weak self, weak dataStack] (note) -> Void in
                     
@@ -334,28 +334,28 @@ public class ICloudStore: CloudStorage {
                             return
                     }
                     
-                    let notification: String
-                    switch NSPersistentStoreUbiquitousTransitionType(rawValue: transitionType.unsignedIntegerValue) {
+                    let notification: Notification.Name
+                    switch NSPersistentStoreUbiquitousTransitionType(rawValue: transitionType.uintValue) {
                         
-                    case .InitialImportCompleted?:
-                        notification = ICloudUbiquitousStoreDidFinishInitialImportNotification
+                    case .initialImportCompleted?:
+                        notification = Notification.Name.iCloudUbiquitousStoreDidFinishInitialImport
                         
-                    case .AccountAdded?:
-                        notification = ICloudUbiquitousStoreDidAddAccountNotification
+                    case .accountAdded?:
+                        notification = Notification.Name.iCloudUbiquitousStoreDidAddAccount
                         
-                    case .AccountRemoved?:
-                        notification = ICloudUbiquitousStoreDidRemoveAccountNotification
+                    case .accountRemoved?:
+                        notification = Notification.Name.iCloudUbiquitousStoreDidRemoveAccount
                         
-                    case .ContentRemoved?:
-                        notification = ICloudUbiquitousStoreDidRemoveContentNotification
+                    case .contentRemoved?:
+                        notification = Notification.Name.iCloudUbiquitousStoreDidRemoveContent
                         
                     default:
                         return
                     }
-                    NSNotificationCenter.defaultCenter().postNotificationName(
-                        notification,
+                    NotificationCenter.default.post(
+                        name: notification,
                         object: self,
-                        userInfo: [UserInfoKeyDataStack: dataStack]
+                        userInfo: [String(describing: DataStack.self): dataStack]
                     )
                 }
             ),
@@ -367,7 +367,7 @@ public class ICloudStore: CloudStorage {
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    public func didRemoveFromDataStack(dataStack: DataStack) {
+    public func didRemoveFromDataStack(_ dataStack: DataStack) {
         
         let coordinator = dataStack.coordinator
         let nilValue: AnyObject? = nil
@@ -391,7 +391,7 @@ public class ICloudStore: CloudStorage {
     /**
      The `NSURL` that points to the ubiquity container file
      */
-    public let cacheFileURL: NSURL
+    public let cacheFileURL: URL
     
     /**
      Options that tell the `DataStack` how to setup the persistent store
@@ -401,20 +401,20 @@ public class ICloudStore: CloudStorage {
     /**
      The options dictionary for the specified `CloudStorageOptions`
      */
-    public func storeOptionsForOptions(options: CloudStorageOptions) -> [String: AnyObject]? {
+    public func dictionary(forOptions options: CloudStorageOptions) -> [AnyHashable: Any]? {
         
-        if options == .None {
+        if options == .none {
             
             return self.storeOptions
         }
         
         var storeOptions = self.storeOptions ?? [:]
-        if options.contains(.AllowSynchronousLightweightMigration) {
+        if options.contains(.allowSynchronousLightweightMigration) {
             
             storeOptions[NSMigratePersistentStoresAutomaticallyOption] = true
             storeOptions[NSInferMappingModelAutomaticallyOption] = true
         }
-        if options.contains(.RecreateLocalStoreOnModelMismatch) {
+        if options.contains(.recreateLocalStoreOnModelMismatch) {
             
             storeOptions[NSPersistentStoreRebuildFromUbiquitousContentOption] = true
         }
@@ -424,48 +424,39 @@ public class ICloudStore: CloudStorage {
     /**
      Called by the `DataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `SQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
      */
-    public func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel?) throws {
+    public func eraseStorageAndWait(soureModel: NSManagedObjectModel) throws {
         
         // TODO: check if attached to persistent store
         
         let cacheFileURL = self.cacheFileURL
-        guard let soureModel = soureModel else {
-            
-            let fileManager = NSFileManager.defaultManager()
-            try fileManager.removeItemAtURL(cacheFileURL)
-            _ = try? fileManager.removeItemAtPath("\(cacheFileURL.absoluteString)-wal")
-            _ = try? fileManager.removeItemAtPath("\(cacheFileURL.absoluteString)-shm")
-            return
-        }
-        try cs_autoreleasepool {
+        try autoreleasepool {
             
             let journalUpdatingCoordinator = NSPersistentStoreCoordinator(managedObjectModel: soureModel)
             let options = [
                 NSSQLitePragmasOption: ["journal_mode": "DELETE"],
                 NSPersistentStoreRemoveUbiquitousMetadataOption: true
-            ]
-            let store = try journalUpdatingCoordinator.addPersistentStoreWithType(
-                self.dynamicType.storeType,
-                configuration: self.configuration,
-                URL: cacheFileURL,
+            ] as [String : Any]
+            let store = try journalUpdatingCoordinator.addPersistentStore(
+                ofType: type(of: self).storeType,
+                configurationName: self.configuration,
+                at: cacheFileURL,
                 options: options
             )
-            try journalUpdatingCoordinator.removePersistentStore(store)
-            try NSPersistentStoreCoordinator.removeUbiquitousContentAndPersistentStoreAtURL(
-                cacheFileURL,
+            try journalUpdatingCoordinator.remove(store)
+            try NSPersistentStoreCoordinator.removeUbiquitousContentAndPersistentStore(
+                at: cacheFileURL,
                 options: options
             )
-            try NSFileManager.defaultManager().removeItemAtURL(cacheFileURL)
         }
     }
     
     
     // MARK: Private
     
-    private struct Static {
+    fileprivate struct Static {
         
-        private static var persistentStoreCoordinatorWillChangeStores: Void?
-        private static var persistentStoreCoordinatorDidChangeStores: Void?
+        fileprivate static var persistentStoreCoordinatorWillChangeStores: Void?
+        fileprivate static var persistentStoreCoordinatorDidChangeStores: Void?
     }
     
     private var willFinishInitialImportKey: Void?
@@ -479,7 +470,7 @@ public class ICloudStore: CloudStorage {
     
     private weak var dataStack: DataStack?
     
-    private func registerNotification(notificationKey: UnsafePointer, name: String, toObserver observer: T, callback: (observer: T, storage: ICloudStore, dataStack: DataStack) -> Void) {
+    private func registerNotification(_ notificationKey: UnsafeRawPointer, name: Notification.Name, toObserver observer: T, callback: @escaping (_ observer: T, _ storage: ICloudStore, _ dataStack: DataStack) -> Void) {
         
         cs_setAssociatedRetainedObject(
             NotificationObserver(
@@ -489,12 +480,12 @@ public class ICloudStore: CloudStorage {
                     
                     guard let `self` = self,
                         let observer = observer,
-                        let dataStack = note.userInfo?[UserInfoKeyDataStack] as? DataStack
-                        where self.dataStack === dataStack else {
+                        let dataStack = note.userInfo?[String(describing: DataStack.self)] as? DataStack,
+                        self.dataStack === dataStack else {
                             
                             return
                     }
-                    callback(observer: observer, storage: self, dataStack: dataStack)
+                    callback(observer, self, dataStack)
                 }
             ),
             forKey: notificationKey,
@@ -505,16 +496,17 @@ public class ICloudStore: CloudStorage {
 
 
 // MARK: - Notification Keys
-
-private let ICloudUbiquitousStoreWillFinishInitialImportNotification = "ICloudUbiquitousStoreWillFinishInitialImportNotification"
-private let ICloudUbiquitousStoreDidFinishInitialImportNotification = "ICloudUbiquitousStoreDidFinishInitialImportNotification"
-private let ICloudUbiquitousStoreWillAddAccountNotification = "ICloudUbiquitousStoreWillAddAccountNotification"
-private let ICloudUbiquitousStoreDidAddAccountNotification = "ICloudUbiquitousStoreDidAddAccountNotification"
-private let ICloudUbiquitousStoreWillRemoveAccountNotification = "ICloudUbiquitousStoreWillRemoveAccountNotification"
-private let ICloudUbiquitousStoreDidRemoveAccountNotification = "ICloudUbiquitousStoreDidRemoveAccountNotification"
-private let ICloudUbiquitousStoreWillRemoveContentNotification = "ICloudUbiquitousStoreWillRemoveContentNotification"
-private let ICloudUbiquitousStoreDidRemoveContentNotification = "ICloudUbiquitousStoreDidRemoveContentNotification"
-
-private let UserInfoKeyDataStack = "UserInfoKeyDataStack"
+    
+fileprivate extension Notification.Name {
+    
+    fileprivate static let iCloudUbiquitousStoreWillFinishInitialImport = Notification.Name(rawValue: "iCloudUbiquitousStoreWillFinishInitialImport")
+    fileprivate static let iCloudUbiquitousStoreDidFinishInitialImport = Notification.Name(rawValue: "iCloudUbiquitousStoreDidFinishInitialImport")
+    fileprivate static let iCloudUbiquitousStoreWillAddAccount = Notification.Name(rawValue: "iCloudUbiquitousStoreWillAddAccount")
+    fileprivate static let iCloudUbiquitousStoreDidAddAccount = Notification.Name(rawValue: "iCloudUbiquitousStoreDidAddAccount")
+    fileprivate static let iCloudUbiquitousStoreWillRemoveAccount = Notification.Name(rawValue: "iCloudUbiquitousStoreWillRemoveAccount")
+    fileprivate static let iCloudUbiquitousStoreDidRemoveAccount = Notification.Name(rawValue: "iCloudUbiquitousStoreDidRemoveAccount")
+    fileprivate static let iCloudUbiquitousStoreWillRemoveContent = Notification.Name(rawValue: "iCloudUbiquitousStoreWillRemoveContent")
+    fileprivate static let iCloudUbiquitousStoreDidRemoveContent = Notification.Name(rawValue: "iCloudUbiquitousStoreDidRemoveContent")
+}
 
 #endif
diff --git a/Sources/Setup/StorageInterfaces/ICloudStoreObserver.swift b/Sources/Setup/StorageInterfaces/ICloudStoreObserver.swift
index edd5b6e..c76cf54 100644
--- a/Sources/Setup/StorageInterfaces/ICloudStoreObserver.swift
+++ b/Sources/Setup/StorageInterfaces/ICloudStoreObserver.swift
@@ -45,7 +45,7 @@ public protocol ICloudStoreObserver: class {
      - parameter storage: the `ICloudStore` instance being observed
      - parameter dataStack: the `DataStack` that manages the peristent store
      */
-    func iCloudStoreWillFinishUbiquitousStoreInitialImport(storage storage: ICloudStore, dataStack: DataStack)
+    func iCloudStoreWillFinishUbiquitousStoreInitialImport(storage: ICloudStore, dataStack: DataStack)
     
     /**
      Notifies that the initial ubiquitous store import completed
@@ -53,7 +53,7 @@ public protocol ICloudStoreObserver: class {
      - parameter storage: the `ICloudStore` instance being observed
      - parameter dataStack: the `DataStack` that manages the peristent store
      */
-    func iCloudStoreDidFinishUbiquitousStoreInitialImport(storage storage: ICloudStore, dataStack: DataStack)
+    func iCloudStoreDidFinishUbiquitousStoreInitialImport(storage: ICloudStore, dataStack: DataStack)
     
     /**
      Notifies that an iCloud account will be added to the coordinator
@@ -61,7 +61,7 @@ public protocol ICloudStoreObserver: class {
      - parameter storage: the `ICloudStore` instance being observed
      - parameter dataStack: the `DataStack` that manages the peristent store
      */
-    func iCloudStoreWillAddAccount(storage storage: ICloudStore, dataStack: DataStack)
+    func iCloudStoreWillAddAccount(storage: ICloudStore, dataStack: DataStack)
     
     /**
      Notifies that an iCloud account was added to the coordinator
@@ -69,7 +69,7 @@ public protocol ICloudStoreObserver: class {
      - parameter storage: the `ICloudStore` instance being observed
      - parameter dataStack: the `DataStack` that manages the peristent store
      */
-    func iCloudStoreDidAddAccount(storage storage: ICloudStore, dataStack: DataStack)
+    func iCloudStoreDidAddAccount(storage: ICloudStore, dataStack: DataStack)
     
     /**
      Notifies that an iCloud account will be removed from the coordinator
@@ -77,7 +77,7 @@ public protocol ICloudStoreObserver: class {
      - parameter storage: the `ICloudStore` instance being observed
      - parameter dataStack: the `DataStack` that manages the peristent store
      */
-    func iCloudStoreWillRemoveAccount(storage storage: ICloudStore, dataStack: DataStack)
+    func iCloudStoreWillRemoveAccount(storage: ICloudStore, dataStack: DataStack)
     
     /**
      Notifies that an iCloud account was removed from the coordinator
@@ -85,7 +85,7 @@ public protocol ICloudStoreObserver: class {
      - parameter storage: the `ICloudStore` instance being observed
      - parameter dataStack: the `DataStack` that manages the peristent store
      */
-    func iCloudStoreDidRemoveAccount(storage storage: ICloudStore, dataStack: DataStack)
+    func iCloudStoreDidRemoveAccount(storage: ICloudStore, dataStack: DataStack)
     
     /**
      Notifies that iCloud contents will be deleted
@@ -93,7 +93,7 @@ public protocol ICloudStoreObserver: class {
      - parameter storage: the `ICloudStore` instance being observed
      - parameter dataStack: the `DataStack` that manages the peristent store
      */
-    func iCloudStoreWillRemoveContent(storage storage: ICloudStore, dataStack: DataStack)
+    func iCloudStoreWillRemoveContent(storage: ICloudStore, dataStack: DataStack)
     
     /**
      Notifies that iCloud contents were deleted
@@ -101,26 +101,26 @@ public protocol ICloudStoreObserver: class {
      - parameter storage: the `ICloudStore` instance being observed
      - parameter dataStack: the `DataStack` that manages the peristent store
      */
-    func iCloudStoreDidRemoveContent(storage storage: ICloudStore, dataStack: DataStack)
+    func iCloudStoreDidRemoveContent(storage: ICloudStore, dataStack: DataStack)
 }
 
 public extension ICloudStoreObserver {
     
-    public func iCloudStoreWillFinishUbiquitousStoreInitialImport(storage storage: ICloudStore, dataStack: DataStack) {}
+    public func iCloudStoreWillFinishUbiquitousStoreInitialImport(storage: ICloudStore, dataStack: DataStack) {}
     
-    public func iCloudStoreDidFinishUbiquitousStoreInitialImport(storage storage: ICloudStore, dataStack: DataStack) {}
+    public func iCloudStoreDidFinishUbiquitousStoreInitialImport(storage: ICloudStore, dataStack: DataStack) {}
     
-    public func iCloudStoreWillAddAccount(storage storage: ICloudStore, dataStack: DataStack) {}
+    public func iCloudStoreWillAddAccount(storage: ICloudStore, dataStack: DataStack) {}
     
-    public func iCloudStoreDidAddAccount(storage storage: ICloudStore, dataStack: DataStack) {}
+    public func iCloudStoreDidAddAccount(storage: ICloudStore, dataStack: DataStack) {}
     
-    public func iCloudStoreWillRemoveAccount(storage storage: ICloudStore, dataStack: DataStack) {}
+    public func iCloudStoreWillRemoveAccount(storage: ICloudStore, dataStack: DataStack) {}
     
-    public func iCloudStoreDidRemoveAccount(storage storage: ICloudStore, dataStack: DataStack) {}
+    public func iCloudStoreDidRemoveAccount(storage: ICloudStore, dataStack: DataStack) {}
     
-    public func iCloudStoreWillRemoveContent(storage storage: ICloudStore, dataStack: DataStack) {}
+    public func iCloudStoreWillRemoveContent(storage: ICloudStore, dataStack: DataStack) {}
     
-    public func iCloudStoreDidRemoveContent(storage storage: ICloudStore, dataStack: DataStack) {}
+    public func iCloudStoreDidRemoveContent(storage: ICloudStore, dataStack: DataStack) {}
 }
 
 #endif
diff --git a/Sources/Setup/StorageInterfaces/InMemoryStore.swift b/Sources/Setup/StorageInterfaces/InMemoryStore.swift
index ae9a576..8829773 100644
--- a/Sources/Setup/StorageInterfaces/InMemoryStore.swift
+++ b/Sources/Setup/StorageInterfaces/InMemoryStore.swift
@@ -69,12 +69,12 @@ public final class InMemoryStore: StorageInterface, DefaultInitializableStore {
     /**
      The options dictionary for the `NSPersistentStore`. For `InMemoryStore`s, this is always set to `nil`.
      */
-    public let storeOptions: [String: AnyObject]? = nil
+    public let storeOptions: [AnyHashable: Any]? = nil
     
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    public func didAddToDataStack(dataStack: DataStack) {
+    public func didAddToDataStack(_ dataStack: DataStack) {
         
         self.dataStack = dataStack
     }
@@ -82,7 +82,7 @@ public final class InMemoryStore: StorageInterface, DefaultInitializableStore {
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    public func didRemoveFromDataStack(dataStack: DataStack) {
+    public func didRemoveFromDataStack(_ dataStack: DataStack) {
         
         self.dataStack = nil
     }
diff --git a/Sources/Setup/StorageInterfaces/LegacySQLiteStore.swift b/Sources/Setup/StorageInterfaces/LegacySQLiteStore.swift
index f3abdd9..e0e1c0a 100644
--- a/Sources/Setup/StorageInterfaces/LegacySQLiteStore.swift
+++ b/Sources/Setup/StorageInterfaces/LegacySQLiteStore.swift
@@ -44,7 +44,7 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
      - parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
      - parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
      */
-    public init(fileURL: NSURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) {
+    public init(fileURL: URL, configuration: String? = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
         
         self.fileURL = fileURL
         self.configuration = configuration
@@ -61,11 +61,12 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
      - parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
      - parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
      */
-    public init(fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) {
+    public init(fileName: String, configuration: String? = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
         
-        self.fileURL = LegacySQLiteStore.defaultRootDirectory.URLByAppendingPathComponent(
+        self.fileURL = LegacySQLiteStore.defaultRootDirectory.appendingPathComponent(
             fileName,
-            isDirectory: false)!
+            isDirectory: false
+        )
         self.configuration = configuration
         self.mappingModelBundles = mappingModelBundles
         self.localStorageOptions = localStorageOptions
@@ -83,7 +84,7 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
         
         self.fileURL = LegacySQLiteStore.defaultFileURL
         self.configuration = nil
-        self.mappingModelBundles = NSBundle.allBundles()
+        self.mappingModelBundles = Bundle.allBundles
         self.localStorageOptions = nil
     }
     
@@ -98,15 +99,15 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
     /**
      The options dictionary for the specified `LocalStorageOptions`
      */
-    public func storeOptionsForOptions(options: LocalStorageOptions) -> [String: AnyObject]? {
+    public func dictionary(forOptions options: LocalStorageOptions) -> [AnyHashable: Any]? {
         
-        if options == .None {
+        if options == .none {
             
             return self.storeOptions
         }
         
         var storeOptions = self.storeOptions ?? [:]
-        if options.contains(.AllowSynchronousLightweightMigration) {
+        if options.contains(.allowSynchronousLightweightMigration) {
             
             storeOptions[NSMigratePersistentStoresAutomaticallyOption] = true
             storeOptions[NSInferMappingModelAutomaticallyOption] = true
@@ -125,12 +126,12 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
      [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
      ```
      */
-    public let storeOptions: [String: AnyObject]? = [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
+    public let storeOptions: [AnyHashable: Any]? = [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
     
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    public func didAddToDataStack(dataStack: DataStack) {
+    public func didAddToDataStack(_ dataStack: DataStack) {
         
         self.dataStack = dataStack
     }
@@ -138,7 +139,7 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    public func didRemoveFromDataStack(dataStack: DataStack) {
+    public func didRemoveFromDataStack(_ dataStack: DataStack) {
         
         self.dataStack = nil
     }
@@ -149,12 +150,12 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
     /**
      The `NSURL` that points to the SQLite file
      */
-    public let fileURL: NSURL
+    public let fileURL: URL
     
     /**
      The `NSBundle`s from which to search mapping models for migrations
      */
-    public let mappingModelBundles: [NSBundle]
+    public let mappingModelBundles: [Bundle]
     
     /**
      Options that tell the `DataStack` how to setup the persistent store
@@ -164,53 +165,90 @@ public final class LegacySQLiteStore: LocalStorage, DefaultInitializableStore {
     /**
      Called by the `DataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `SQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
      */
-    public func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel?) throws {
+    public func eraseStorageAndWait(metadata: [String: Any], soureModelHint: NSManagedObjectModel?) throws {
         
         // TODO: check if attached to persistent store
         
-        let fileURL = self.fileURL
-        guard let soureModel = soureModel else {
+        func deleteFiles(storeURL: URL, extraFiles: [String] = []) throws {
             
-            let fileManager = NSFileManager.defaultManager()
-            try fileManager.removeItemAtURL(fileURL)
-            _ = try? fileManager.removeItemAtPath("\(fileURL.absoluteString)-wal")
-            _ = try? fileManager.removeItemAtPath("\(fileURL.absoluteString)-shm")
-            return
+            let fileManager = FileManager.default
+            let extraFiles: [String] = [
+                storeURL.path.appending("-wal"),
+                storeURL.path.appending("-shm")
+            ]
+            do {
+                
+                let trashURL = URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!)
+                    .appendingPathComponent(Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack", isDirectory: true)
+                    .appendingPathComponent("trash", isDirectory: true)
+                try fileManager.createDirectory(
+                    at: trashURL,
+                    withIntermediateDirectories: true,
+                    attributes: nil
+                )
+                
+                let temporaryFileURL = trashURL.appendingPathComponent(UUID().uuidString, isDirectory: false)
+                try fileManager.moveItem(at: storeURL, to: temporaryFileURL)
+                
+                let extraTemporaryFiles = extraFiles.map { (extraFile) -> String in
+                    
+                    let temporaryFile = trashURL.appendingPathComponent(UUID().uuidString, isDirectory: false).path
+                    if let _ = try? fileManager.moveItem(atPath: extraFile, toPath: temporaryFile) {
+                        
+                        return temporaryFile
+                    }
+                    return extraFile
+                }
+                DispatchQueue.global(qos: .background).async {
+                    
+                    _ = try? fileManager.removeItem(at: temporaryFileURL)
+                    extraTemporaryFiles.forEach({ _ = try? fileManager.removeItem(atPath: $0) })
+                }
+            }
+            catch {
+                
+                try fileManager.removeItem(at: storeURL)
+                extraFiles.forEach({ _ = try? fileManager.removeItem(atPath: $0) })
+            }
         }
-        try cs_autoreleasepool {
+        
+        let fileURL = self.fileURL
+        try autoreleasepool {
             
-            let journalUpdatingCoordinator = NSPersistentStoreCoordinator(managedObjectModel: soureModel)
-            let store = try journalUpdatingCoordinator.addPersistentStoreWithType(
-                self.dynamicType.storeType,
-                configuration: self.configuration,
-                URL: fileURL,
-                options: [NSSQLitePragmasOption: ["journal_mode": "DELETE"]]
-            )
-            try journalUpdatingCoordinator.removePersistentStore(store)
-            try NSFileManager.defaultManager().removeItemAtURL(fileURL)
+            if let soureModel = soureModelHint ?? NSManagedObjectModel.mergedModel(from: nil, forStoreMetadata: metadata) {
+                
+                let journalUpdatingCoordinator = NSPersistentStoreCoordinator(managedObjectModel: soureModel)
+                let store = try journalUpdatingCoordinator.addPersistentStore(
+                    ofType: type(of: self).storeType,
+                    configurationName: self.configuration,
+                    at: fileURL,
+                    options: [NSSQLitePragmasOption: ["journal_mode": "DELETE"]]
+                )
+                try journalUpdatingCoordinator.remove(store)
+            }
+            try deleteFiles(storeURL: fileURL)
         }
     }
     
     
     // MARK: Internal
     
-    internal static let defaultRootDirectory: NSURL = {
+    internal static let defaultRootDirectory: URL = {
         
         #if os(tvOS)
-            let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory
+            let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory
         #else
-            let systemDirectorySearchPath = NSSearchPathDirectory.ApplicationSupportDirectory
+            let systemDirectorySearchPath = FileManager.SearchPathDirectory.applicationSupportDirectory
         #endif
         
-        return NSFileManager.defaultManager().URLsForDirectory(
-            systemDirectorySearchPath,
-            inDomains: .UserDomainMask
-            ).first!
+        return FileManager.default.urls(
+            for: systemDirectorySearchPath,
+            in: .userDomainMask).first!
     }()
     
     internal static let defaultFileURL = LegacySQLiteStore.defaultRootDirectory
-        .URLByAppendingPathComponent(DataStack.applicationName, isDirectory: false)!
-        .URLByAppendingPathExtension("sqlite")!
+        .appendingPathComponent(DataStack.applicationName, isDirectory: false)
+        .appendingPathExtension("sqlite")
     
     
     // MARK: Private
diff --git a/Sources/Setup/StorageInterfaces/SQLiteStore.swift b/Sources/Setup/StorageInterfaces/SQLiteStore.swift
index 15c273c..815b9d7 100644
--- a/Sources/Setup/StorageInterfaces/SQLiteStore.swift
+++ b/Sources/Setup/StorageInterfaces/SQLiteStore.swift
@@ -43,7 +43,7 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
      - parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models (*.xcmappingmodel) for migration.
      - parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
      */
-    public init(fileURL: NSURL, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) {
+    public init(fileURL: URL, configuration: String? = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
         
         self.fileURL = fileURL
         self.configuration = configuration
@@ -60,10 +60,10 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
      - parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models (*.xcmappingmodel) for migration
      - parameter localStorageOptions: When the `SQLiteStore` is passed to the `DataStack`'s `addStorage()` methods, tells the `DataStack` how to setup the persistent store. Defaults to `.None`.
      */
-    public init(fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle] = NSBundle.allBundles(), localStorageOptions: LocalStorageOptions = nil) {
+    public init(fileName: String, configuration: String? = nil, mappingModelBundles: [Bundle] = Bundle.allBundles, localStorageOptions: LocalStorageOptions = nil) {
         
         self.fileURL = SQLiteStore.defaultRootDirectory
-            .URLByAppendingPathComponent(fileName, isDirectory: false)!
+            .appendingPathComponent(fileName, isDirectory: false)
         self.configuration = configuration
         self.mappingModelBundles = mappingModelBundles
         self.localStorageOptions = localStorageOptions
@@ -79,9 +79,9 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
      */
     public init() {
         
-        self.fileURL = SQLiteStore.defaultFileURL!
+        self.fileURL = SQLiteStore.defaultFileURL
         self.configuration = nil
-        self.mappingModelBundles = NSBundle.allBundles()
+        self.mappingModelBundles = Bundle.allBundles
         self.localStorageOptions = nil
     }
     
@@ -104,12 +104,12 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
      [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
      ```
      */
-    public let storeOptions: [String: AnyObject]? = [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
+    public let storeOptions: [AnyHashable: Any]? = [NSSQLitePragmasOption: ["journal_mode": "WAL"]]
     
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    public func didAddToDataStack(dataStack: DataStack) {
+    public func didAddToDataStack(_ dataStack: DataStack) {
         
         self.dataStack = dataStack
     }
@@ -117,7 +117,7 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    public func didRemoveFromDataStack(dataStack: DataStack) {
+    public func didRemoveFromDataStack(_ dataStack: DataStack) {
         
         self.dataStack = nil
     }
@@ -128,12 +128,12 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
     /**
      The `NSURL` that points to the SQLite file
      */
-    public let fileURL: NSURL
+    public let fileURL: URL
     
     /**
      The `NSBundle`s from which to search mapping models for migrations
      */
-    public let mappingModelBundles: [NSBundle]
+    public let mappingModelBundles: [Bundle]
     
     /**
      Options that tell the `DataStack` how to setup the persistent store
@@ -143,15 +143,15 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
     /**
      The options dictionary for the specified `LocalStorageOptions`
      */
-    public func storeOptionsForOptions(options: LocalStorageOptions) -> [String: AnyObject]? {
+    public func dictionary(forOptions options: LocalStorageOptions) -> [AnyHashable: Any]? {
         
-        if options == .None {
+        if options == .none {
             
             return self.storeOptions
         }
         
         var storeOptions = self.storeOptions ?? [:]
-        if options.contains(.AllowSynchronousLightweightMigration) {
+        if options.contains(.allowSynchronousLightweightMigration) {
             
             storeOptions[NSMigratePersistentStoresAutomaticallyOption] = true
             storeOptions[NSInferMappingModelAutomaticallyOption] = true
@@ -162,58 +162,98 @@ public final class SQLiteStore: LocalStorage, DefaultInitializableStore {
     /**
      Called by the `DataStack` to perform actual deletion of the store file from disk. Do not call directly! The `sourceModel` argument is a hint for the existing store's model version. For `SQLiteStore`, this converts the database's WAL journaling mode to DELETE before deleting the file.
      */
-    public func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel?) throws {
+    public func eraseStorageAndWait(metadata: [String: Any], soureModelHint: NSManagedObjectModel?) throws {
         
         // TODO: check if attached to persistent store
         
-        let fileURL = self.fileURL
-        guard let soureModel = soureModel else {
+        func deleteFiles(storeURL: URL, extraFiles: [String] = []) throws {
             
-            let fileManager = NSFileManager.defaultManager()
-            try fileManager.removeItemAtURL(fileURL)
-            _ = try? fileManager.removeItemAtPath("\(fileURL.absoluteString)-wal")
-            _ = try? fileManager.removeItemAtPath("\(fileURL.absoluteString)-shm")
-            return
+            let fileManager = FileManager.default
+            let extraFiles: [String] = [
+                storeURL.path.appending("-wal"),
+                storeURL.path.appending("-shm")
+            ]
+            do {
+                
+                let trashURL = URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!)
+                    .appendingPathComponent(Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack", isDirectory: true)
+                    .appendingPathComponent("trash", isDirectory: true)
+                try fileManager.createDirectory(
+                    at: trashURL,
+                    withIntermediateDirectories: true,
+                    attributes: nil
+                )
+                
+                let temporaryFileURL = trashURL.appendingPathComponent(UUID().uuidString, isDirectory: false)
+                try fileManager.moveItem(at: storeURL, to: temporaryFileURL)
+                
+                let extraTemporaryFiles = extraFiles.map { (extraFile) -> String in
+                    
+                    let temporaryFile = trashURL.appendingPathComponent(UUID().uuidString, isDirectory: false).path
+                    if let _ = try? fileManager.moveItem(atPath: extraFile, toPath: temporaryFile) {
+                        
+                        return temporaryFile
+                    }
+                    return extraFile
+                }
+                DispatchQueue.global(qos: .background).async {
+                    
+                    _ = try? fileManager.removeItem(at: temporaryFileURL)
+                    extraTemporaryFiles.forEach({ _ = try? fileManager.removeItem(atPath: $0) })
+                }
+            }
+            catch {
+                
+                try fileManager.removeItem(at: storeURL)
+                extraFiles.forEach({ _ = try? fileManager.removeItem(atPath: $0) })
+            }
         }
-        try cs_autoreleasepool {
+        
+        let fileURL = self.fileURL
+        try autoreleasepool {
             
-            let journalUpdatingCoordinator = NSPersistentStoreCoordinator(managedObjectModel: soureModel)
-            let store = try journalUpdatingCoordinator.addPersistentStoreWithType(
-                self.dynamicType.storeType,
-                configuration: self.configuration,
-                URL: fileURL,
-                options: [NSSQLitePragmasOption: ["journal_mode": "DELETE"]]
-            )
-            try journalUpdatingCoordinator.removePersistentStore(store)
-            try NSFileManager.defaultManager().removeItemAtURL(fileURL)
+            if let soureModel = soureModelHint ?? NSManagedObjectModel.mergedModel(from: nil, forStoreMetadata: metadata) {
+                
+                let journalUpdatingCoordinator = NSPersistentStoreCoordinator(managedObjectModel: soureModel)
+                let store = try journalUpdatingCoordinator.addPersistentStore(
+                    ofType: type(of: self).storeType,
+                    configurationName: self.configuration,
+                    at: fileURL,
+                    options: [NSSQLitePragmasOption: ["journal_mode": "DELETE"]]
+                )
+                try journalUpdatingCoordinator.remove(store)
+            }
+            try deleteFiles(storeURL: fileURL)
         }
     }
     
     
     // MARK: Internal
     
-    internal static let defaultRootDirectory: NSURL = {
+    internal static let defaultRootDirectory: URL = {
         
         #if os(tvOS)
-            let systemDirectorySearchPath = NSSearchPathDirectory.CachesDirectory
+            let systemDirectorySearchPath = FileManager.SearchPathDirectory.cachesDirectory
         #else
-            let systemDirectorySearchPath = NSSearchPathDirectory.ApplicationSupportDirectory
+            let systemDirectorySearchPath = FileManager.SearchPathDirectory.applicationSupportDirectory
         #endif
         
-        let defaultSystemDirectory = NSFileManager
-            .defaultManager()
-            .URLsForDirectory(systemDirectorySearchPath, inDomains: .UserDomainMask).first!
+        let defaultSystemDirectory = FileManager.default.urls(
+                for: systemDirectorySearchPath,
+                in: .userDomainMask).first!
         
-        return defaultSystemDirectory.URLByAppendingPathComponent(
-            NSBundle.mainBundle().bundleIdentifier ?? "com.CoreStore.DataStack",
-            isDirectory: true)!
+        return defaultSystemDirectory.appendingPathComponent(
+            Bundle.main.bundleIdentifier ?? "com.CoreStore.DataStack",
+            isDirectory: true
+        )
     }()
     
     internal static let defaultFileURL = SQLiteStore.defaultRootDirectory
-        .URLByAppendingPathComponent(
-            (NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as? String) ?? "CoreData",
-            isDirectory: false)!
-        .URLByAppendingPathExtension("sqlite")
+        .appendingPathComponent(
+            (Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String) ?? "CoreData",
+            isDirectory: false
+        )
+        .appendingPathExtension("sqlite")
     
     
     // MARK: Private
diff --git a/Sources/Setup/StorageInterfaces/StorageInterface.swift b/Sources/Setup/StorageInterfaces/StorageInterface.swift
index 3e10b3c..28444bb 100644
--- a/Sources/Setup/StorageInterfaces/StorageInterface.swift
+++ b/Sources/Setup/StorageInterfaces/StorageInterface.swift
@@ -46,7 +46,7 @@ public protocol StorageInterface: class {
     /**
      The options dictionary for the `NSPersistentStore`
      */
-    var storeOptions: [String: AnyObject]? { get }
+    var storeOptions: [AnyHashable: Any]? { get }
     
     
     // MARK: Internal (Do not call these directly)
@@ -54,12 +54,12 @@ public protocol StorageInterface: class {
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    func didAddToDataStack(dataStack: DataStack)
+    func didAddToDataStack(_ dataStack: DataStack)
     
     /**
      Do not call directly. Used by the `DataStack` internally.
      */
-    func didRemoveFromDataStack(dataStack: DataStack)
+    func didRemoveFromDataStack(_ dataStack: DataStack)
 }
 
 
@@ -82,27 +82,27 @@ public protocol DefaultInitializableStore: StorageInterface {
 /**
  The `LocalStorageOptions` provides settings that tells the `DataStack` how to setup the persistent store for `LocalStorage` implementers.
  */
-public struct LocalStorageOptions: OptionSetType, NilLiteralConvertible {
+public struct LocalStorageOptions: OptionSet, ExpressibleByNilLiteral {
     
     /**
      Tells the `DataStack` that the store should not be migrated or recreated, and should simply fail on model mismatch
      */
-    public static let None = LocalStorageOptions(rawValue: 0)
+    public static let none = LocalStorageOptions(rawValue: 0)
     
     /**
      Tells the `DataStack` to delete and recreate the store on model mismatch, otherwise exceptions will be thrown on failure instead
      */
-    public static let RecreateStoreOnModelMismatch = LocalStorageOptions(rawValue: 1 << 0)
+    public static let recreateStoreOnModelMismatch = LocalStorageOptions(rawValue: 1 << 0)
     
     /**
      Tells the `DataStack` to prevent progressive migrations for the store
      */
-    public static let PreventProgressiveMigration = LocalStorageOptions(rawValue: 1 << 1)
+    public static let preventProgressiveMigration = LocalStorageOptions(rawValue: 1 << 1)
     
     /**
      Tells the `DataStack` to allow lightweight migration for the store when added synchronously
      */
-    public static let AllowSynchronousLightweightMigration = LocalStorageOptions(rawValue: 1 << 2)
+    public static let allowSynchronousLightweightMigration = LocalStorageOptions(rawValue: 1 << 2)
     
     
     
@@ -119,7 +119,7 @@ public struct LocalStorageOptions: OptionSetType, NilLiteralConvertible {
     public let rawValue: Int
     
     
-    // MARK: NilLiteralConvertible
+    // MARK: ExpressibleByNilLiteral
     
     public init(nilLiteral: ()) {
         
@@ -138,12 +138,12 @@ public protocol LocalStorage: StorageInterface {
     /**
      The `NSURL` that points to the store file
      */
-    var fileURL: NSURL { get }
+    var fileURL: URL { get }
     
     /**
      The `NSBundle`s from which to search mapping models (*.xcmappingmodel) for migrations
      */
-    var mappingModelBundles: [NSBundle] { get }
+    var mappingModelBundles: [Bundle] { get }
     
     /**
      Options that tell the `DataStack` how to setup the persistent store
@@ -153,21 +153,21 @@ public protocol LocalStorage: StorageInterface {
     /**
      The options dictionary for the specified `LocalStorageOptions`
      */
-    func storeOptionsForOptions(options: LocalStorageOptions) -> [String: AnyObject]?
+    func dictionary(forOptions options: LocalStorageOptions) -> [AnyHashable: Any]?
     
     /**
      Called by the `DataStack` to perform actual deletion of the store file from disk. **Do not call directly!** The `sourceModel` argument is a hint for the existing store's model version. Implementers can use the `sourceModel` to perform necessary store operations. (SQLite stores for example, can convert WAL journaling mode to DELETE before deleting)
      */
-    func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel?) throws
+    func eraseStorageAndWait(metadata: [String: Any], soureModelHint: NSManagedObjectModel?) throws
 }
 
 internal extension LocalStorage {
     
-    internal func matchesPersistentStore(persistentStore: NSPersistentStore) -> Bool {
+    internal func matchesPersistentStore(_ persistentStore: NSPersistentStore) -> Bool {
         
-        return persistentStore.type == self.dynamicType.storeType
+        return persistentStore.type == type(of: self).storeType
             && persistentStore.configurationName == (self.configuration ?? Into.defaultConfigurationName)
-            && persistentStore.URL == self.fileURL
+            && persistentStore.url == self.fileURL
     }
 }
 
@@ -177,22 +177,22 @@ internal extension LocalStorage {
 /**
  The `CloudStorageOptions` provides settings that tells the `DataStack` how to setup the persistent store for `LocalStorage` implementers.
  */
-public struct CloudStorageOptions: OptionSetType, NilLiteralConvertible {
+public struct CloudStorageOptions: OptionSet, ExpressibleByNilLiteral {
     
     /**
      Tells the `DataStack` that the store should not be migrated or recreated, and should simply fail on model mismatch
      */
-    public static let None = CloudStorageOptions(rawValue: 0)
+    public static let none = CloudStorageOptions(rawValue: 0)
     
     /**
      Tells the `DataStack` to delete and recreate the local store from the cloud store on model mismatch, otherwise exceptions will be thrown on failure instead
      */
-    public static let RecreateLocalStoreOnModelMismatch = CloudStorageOptions(rawValue: 1 << 0)
+    public static let recreateLocalStoreOnModelMismatch = CloudStorageOptions(rawValue: 1 << 0)
     
     /**
      Tells the `DataStack` to allow lightweight migration for the store when added synchronously
      */
-    public static let AllowSynchronousLightweightMigration = CloudStorageOptions(rawValue: 1 << 2)
+    public static let allowSynchronousLightweightMigration = CloudStorageOptions(rawValue: 1 << 2)
     
     
     // MARK: OptionSetType
@@ -208,7 +208,7 @@ public struct CloudStorageOptions: OptionSetType, NilLiteralConvertible {
     public let rawValue: Int
     
     
-    // MARK: NilLiteralConvertible
+    // MARK: ExpressibleByNilLiteral
     
     public init(nilLiteral: ()) {
         
@@ -227,7 +227,7 @@ public protocol CloudStorage: StorageInterface {
     /**
      The `NSURL` that points to the store file
      */
-    var cacheFileURL: NSURL { get }
+    var cacheFileURL: URL { get }
     
     /**
      Options that tell the `DataStack` how to setup the persistent store
@@ -237,24 +237,24 @@ public protocol CloudStorage: StorageInterface {
     /**
      The options dictionary for the specified `CloudStorageOptions`
      */
-    func storeOptionsForOptions(options: CloudStorageOptions) -> [String: AnyObject]?
+    func dictionary(forOptions options: CloudStorageOptions) -> [AnyHashable: Any]?
     
     /**
      Called by the `DataStack` to perform actual deletion of the store file from disk. **Do not call directly!** The `sourceModel` argument is a hint for the existing store's model version. Implementers can use the `sourceModel` to perform necessary store operations. (Cloud stores for example, can set the NSPersistentStoreRemoveUbiquitousMetadataOption option before deleting)
      */
-    func eraseStorageAndWait(soureModel soureModel: NSManagedObjectModel?) throws
+    func eraseStorageAndWait(soureModel: NSManagedObjectModel) throws
 }
 
 internal extension CloudStorage {
     
-    internal func matchesPersistentStore(persistentStore: NSPersistentStore) -> Bool {
+    internal func matchesPersistentStore(_ persistentStore: NSPersistentStore) -> Bool {
         
-        guard persistentStore.type == self.dynamicType.storeType
+        guard persistentStore.type == type(of: self).storeType
             && persistentStore.configurationName == (self.configuration ?? Into.defaultConfigurationName) else {
                 
                 return false
         }
-        guard persistentStore.URL == self.cacheFileURL else {
+        guard persistentStore.url == self.cacheFileURL else {
             
             return false
         }
diff --git a/Sources/Transactions/AsynchronousDataTransaction.swift b/Sources/Transactions/AsynchronousDataTransaction.swift
index f601634..6a0dcb4 100644
--- a/Sources/Transactions/AsynchronousDataTransaction.swift
+++ b/Sources/Transactions/AsynchronousDataTransaction.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - AsynchronousDataTransaction
@@ -42,10 +39,10 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
      
      - parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block.
      */
-    public func commit(completion: (result: SaveResult) -> Void = { _ in }) {
+    public func commit(_ completion: @escaping (_ result: SaveResult) -> Void = { _ in }) {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to commit a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -54,12 +51,12 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
         )
         
         self.isCommitted = true
-        let group = GCDGroup()
+        let group = DispatchGroup()
         group.enter()
         self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
             
             self.result = result
-            completion(result: result)
+            completion(result)
             group.leave()
         }
         group.wait()
@@ -71,10 +68,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
      - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
      - returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
      */
-    public func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
+    @discardableResult
+    public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to begin a child transaction from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -97,11 +95,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
      - parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
      - returns: a new `NSManagedObject` instance of the specified entity type.
      */
-    public override func create(into: Into) -> T {
+    public override func create(_ into: Into) -> T {
         
         CoreStore.assert(
             !self.isCommitted,
-            "Attempted to create an entity of type \(cs_typeName(T)) from an already committed \(cs_typeName(self))."
+            "Attempted to create an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
         )
         
         return super.create(into)
@@ -113,8 +111,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(object: T?) -> T? {
+    public override func edit(_ object: T?) -> T? {
         
         CoreStore.assert(
             !self.isCommitted,
@@ -131,12 +128,11 @@ 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(into: Into, _ objectID: NSManagedObjectID) -> T? {
+    public override func edit(_ into: Into, _ objectID: NSManagedObjectID) -> T? {
         
         CoreStore.assert(
             !self.isCommitted,
-            "Attempted to update an entity of type \(cs_typeName(T)) from an already committed \(cs_typeName(self))."
+            "Attempted to update an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
         )
         
         return super.edit(into, objectID)
@@ -147,7 +143,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
      
      - parameter object: the `NSManagedObject` type to be deleted
      */
-    public override func delete(object: NSManagedObject?) {
+    public override func delete(_ object: NSManagedObject?) {
         
         CoreStore.assert(
             !self.isCommitted,
@@ -164,7 +160,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
      - parameter object2: another `NSManagedObject` type to be deleted
      - parameter objects: other `NSManagedObject`s type to be deleted
      */
-    public override func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
+    public override func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
         
         CoreStore.assert(
             !self.isCommitted,
@@ -179,7 +175,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
      
      - parameter objects: the `NSManagedObject`s type to be deleted
      */
-    public override func delete(objects: S) {
+    public override func delete(_ objects: S) where S.Iterator.Element: NSManagedObject {
         
         CoreStore.assert(
             !self.isCommitted,
@@ -192,7 +188,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
     
     // MARK: Internal
     
-    internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, closure: (transaction: AsynchronousDataTransaction) -> Void) {
+    internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
         
         self.closure = closure
         
@@ -203,11 +199,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
         
         self.transactionQueue.async {
             
-            self.closure(transaction: self)
+            self.closure(self)
             if !self.isCommitted && self.hasChanges {
                 
                 CoreStore.log(
-                    .Warning,
+                    .warning,
                     message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
                 )
             }
@@ -218,12 +214,12 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
         
         self.transactionQueue.sync {
             
-            self.closure(transaction: self)
+            self.closure(self)
             
             if !self.isCommitted && self.hasChanges {
                 
                 CoreStore.log(
-                    .Warning,
+                    .warning,
                     message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
                 )
             }
@@ -234,23 +230,5 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
     
     // MARK: Private
     
-    private let closure: (transaction: AsynchronousDataTransaction) -> Void
-    
-    
-    // MARK: Deprecated
-    
-    @available(*, deprecated=1.3.4, obsoleted=2.0.0, message="Resetting the context is inherently unsafe. This method will be removed in the near future. Use `beginUnsafe()` to create transactions with `undo` support.")
-    public func rollback() {
-        
-        CoreStore.assert(
-            !self.isCommitted,
-            "Attempted to rollback an already committed \(cs_typeName(self))."
-        )
-        CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
-            "Attempted to rollback a \(cs_typeName(self)) outside its designated queue."
-        )
-        
-        self.context.reset()
-    }
+    private let closure: (_ transaction: AsynchronousDataTransaction) -> Void
 }
diff --git a/Sources/Transactions/BaseDataTransaction.swift b/Sources/Transactions/BaseDataTransaction.swift
index 103642f..6b6c0ec 100644
--- a/Sources/Transactions/BaseDataTransaction.swift
+++ b/Sources/Transactions/BaseDataTransaction.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - BaseDataTransaction
@@ -53,15 +50,15 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
      - returns: a new `NSManagedObject` instance of the specified entity type.
      */
-    public func create(into: Into) -> T {
+    public func create(_ into: Into) -> T {
         
+        let entityClass = (into.entityClass as! T.Type)
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
-            "Attempted to create an entity of type \(cs_typeName(T)) outside its designated queue."
+            "Attempted to create an entity of type \(cs_typeName(entityClass)) outside its designated queue."
         )
         
         let context = self.context
-        let entityClass = (into.entityClass as! NSManagedObject.Type)
         if into.inferStoreIfPossible {
             
             switch context.parentStack!.persistentStoreForEntityClass(
@@ -71,8 +68,8 @@ public /*abstract*/ class BaseDataTransaction {
             ) {
                 
             case (let persistentStore?, _):
-                let object = entityClass.createInContext(context) as! T
-                context.assignObject(object, toPersistentStore: persistentStore)
+                let object = entityClass.createInContext(context)
+                context.assign(object, to: persistentStore)
                 return object
                 
             case (nil, true):
@@ -87,13 +84,13 @@ public /*abstract*/ class BaseDataTransaction {
             switch context.parentStack!.persistentStoreForEntityClass(
                 entityClass,
                 configuration: into.configuration
-                    ?? into.dynamicType.defaultConfigurationName,
+                    ?? type(of: into).defaultConfigurationName,
                 inferStoreIfPossible: false
             ) {
                 
             case (let persistentStore?, _):
-                let object = entityClass.createInContext(context) as! T
-                context.assignObject(object, toPersistentStore: persistentStore)
+                let object = entityClass.createInContext(context)
+                context.assign(object, to: persistentStore)
                 return object
                 
             case (nil, true):
@@ -118,8 +115,7 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter object: the `NSManagedObject` type to be edited
      - returns: an editable proxy for the specified `NSManagedObject`.
      */
-    @warn_unused_result
-    public func edit(object: T?) -> T? {
+    public func edit(_ object: T?) -> T? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
@@ -139,17 +135,16 @@ 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(into: Into, _ objectID: NSManagedObjectID) -> T? {
+    public func edit(_ into: Into, _ objectID: NSManagedObjectID) -> T? {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
-            "Attempted to update an entity of type \(cs_typeName(T)) outside its designated queue."
+            "Attempted to update an entity of type \(cs_typeName(into.entityClass)) outside its designated queue."
         )
         CoreStore.assert(
             into.inferStoreIfPossible
                 || (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName,
-            "Attempted to update an entity of type \(cs_typeName(T)) but the specified persistent store do not match the `NSManagedObjectID`."
+            "Attempted to update an entity of type \(cs_typeName(into.entityClass)) but the specified persistent store do not match the `NSManagedObjectID`."
         )
         return self.fetchExisting(objectID) as? T
     }
@@ -159,7 +154,7 @@ public /*abstract*/ class BaseDataTransaction {
      
      - parameter object: the `NSManagedObject` to be deleted
      */
-    public func delete(object: NSManagedObject?) {
+    public func delete(_ object: NSManagedObject?) {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
@@ -179,7 +174,7 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter object2: another `NSManagedObject` to be deleted
      - parameter objects: other `NSManagedObject`s to be deleted
      */
-    public func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
+    public func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
         
         self.delete(([object1, object2] + objects).flatMap { $0 })
     }
@@ -189,7 +184,7 @@ public /*abstract*/ class BaseDataTransaction {
      
      - parameter objects: the `NSManagedObject`s to be deleted
      */
-    public func delete(objects: S) {
+    public func delete(_ objects: S) where S.Iterator.Element: NSManagedObject {
         
         CoreStore.assert(
             self.isRunningInAllowedQueue(),
@@ -221,11 +216,10 @@ public /*abstract*/ class BaseDataTransaction {
     
     - returns: a `Set` of pending `NSManagedObject`s that were inserted to the transaction.
      */
-    @warn_unused_result
     public func insertedObjects() -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -242,11 +236,10 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter entity: the `NSManagedObject` subclass to filter
      - returns: a `Set` of pending `NSManagedObject`s of the specified type that were inserted to the transaction.
      */
-    @warn_unused_result
-    public func insertedObjects(entity: T.Type) -> Set {
+    public func insertedObjects(_ entity: T.Type) -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -262,11 +255,10 @@ public /*abstract*/ class BaseDataTransaction {
      
      - returns: a `Set` of pending `NSManagedObjectID`s that were inserted to the transaction.
      */
-    @warn_unused_result
     public func insertedObjectIDs() -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -283,11 +275,10 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter entity: the `NSManagedObject` subclass to filter
      - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
      */
-    @warn_unused_result
-    public func insertedObjectIDs(entity: T.Type) -> Set {
+    public func insertedObjectIDs(_ entity: T.Type) -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -295,7 +286,7 @@ public /*abstract*/ class BaseDataTransaction {
             "Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
         )
         
-        return Set(self.context.insertedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
+        return Set(self.context.insertedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
     }
     
     /**
@@ -303,11 +294,10 @@ public /*abstract*/ class BaseDataTransaction {
      
      - returns: a `Set` of pending `NSManagedObject`s that were updated to the transaction.
      */
-    @warn_unused_result
     public func updatedObjects() -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -324,11 +314,10 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter entity: the `NSManagedObject` subclass to filter
      - returns: a `Set` of pending `NSManagedObject`s of the specified type that were updated in the transaction.
      */
-    @warn_unused_result
-    public func updatedObjects(entity: T.Type) -> Set {
+    public func updatedObjects(_ entity: T.Type) -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -336,7 +325,7 @@ public /*abstract*/ class BaseDataTransaction {
             "Attempted to access updated objects from an already committed \(cs_typeName(self))."
         )
         
-        return Set(self.context.updatedObjects.filter { $0.isKindOfClass(entity) }.map { $0 as! T })
+        return Set(self.context.updatedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
     }
     
     /**
@@ -344,11 +333,10 @@ public /*abstract*/ class BaseDataTransaction {
      
      - returns: a `Set` of pending `NSManagedObjectID`s that were updated in the transaction.
      */
-    @warn_unused_result
     public func updatedObjectIDs() -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -365,11 +353,10 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter entity: the `NSManagedObject` subclass to filter
      - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
      */
-    @warn_unused_result
-    public func updatedObjectIDs(entity: T.Type) -> Set {
+    public func updatedObjectIDs(_ entity: T.Type) -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -377,7 +364,7 @@ public /*abstract*/ class BaseDataTransaction {
             "Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
         )
         
-        return Set(self.context.updatedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
+        return Set(self.context.updatedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
     }
     
     /**
@@ -385,11 +372,10 @@ public /*abstract*/ class BaseDataTransaction {
      
      - returns: a `Set` of pending `NSManagedObject`s that were deleted from the transaction.
      */
-    @warn_unused_result
     public func deletedObjects() -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -406,11 +392,10 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter entity: the `NSManagedObject` subclass to filter
      - returns: a `Set` of pending `NSManagedObject`s of the specified type that were deleted from the transaction.
      */
-    @warn_unused_result
-    public func deletedObjects(entity: T.Type) -> Set {
+    public func deletedObjects(_ entity: T.Type) -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -418,7 +403,7 @@ public /*abstract*/ class BaseDataTransaction {
             "Attempted to access deleted objects from an already committed \(cs_typeName(self))."
         )
         
-        return Set(self.context.deletedObjects.filter { $0.isKindOfClass(entity) }.map { $0 as! T })
+        return Set(self.context.deletedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
     }
     
     /**
@@ -427,11 +412,10 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter entity: the `NSManagedObject` subclass to filter
      - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
      */
-    @warn_unused_result
     public func deletedObjectIDs() -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -448,11 +432,10 @@ public /*abstract*/ class BaseDataTransaction {
      - parameter entity: the `NSManagedObject` subclass to filter
      - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
      */
-    @warn_unused_result
-    public func deletedObjectIDs(entity: T.Type) -> Set {
+    public func deletedObjectIDs(_ entity: T.Type) -> Set {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -460,28 +443,26 @@ public /*abstract*/ class BaseDataTransaction {
             "Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
         )
         
-        return Set(self.context.deletedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
+        return Set(self.context.deletedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
     }
     
     
     // MARK: Internal
     
     internal let context: NSManagedObjectContext
-    internal let transactionQueue: GCDQueue
-    internal let childTransactionQueue: GCDQueue = .createSerial("com.corestore.datastack.childtransactionqueue")
+    internal let transactionQueue: DispatchQueue
+    internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childtransactionqueue")
     internal let supportsUndo: Bool
     internal let bypassesQueueing: Bool
-    
-    
     internal var isCommitted = false
     internal var result: SaveResult?
     
-    internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
+    internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
         
         let context = mainContext.temporaryContextInTransactionWithConcurrencyType(
-            queue == .Main
-                ? .MainQueueConcurrencyType
-                : .PrivateQueueConcurrencyType
+            queue == .main
+                ? .mainQueueConcurrencyType
+                : .privateQueueConcurrencyType
         )
         self.transactionQueue = queue
         self.context = context
@@ -489,18 +470,19 @@ public /*abstract*/ class BaseDataTransaction {
         self.bypassesQueueing = bypassesQueueing
         
         context.parentTransaction = self
+        context.isTransactionContext = true
         if !supportsUndo {
             
             context.undoManager = nil
         }
         else if context.undoManager == nil {
             
-            context.undoManager = NSUndoManager()
+            context.undoManager = UndoManager()
         }
     }
     
     internal func isRunningInAllowedQueue() -> Bool {
         
-        return self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext()
+        return self.bypassesQueueing || self.transactionQueue.cs_isCurrentExecutionContext()
     }
 }
diff --git a/Sources/Transactions/CoreStore+Transaction.swift b/Sources/Transactions/CoreStore+Transaction.swift
index 06a0f2d..23b5bd0 100644
--- a/Sources/Transactions/CoreStore+Transaction.swift
+++ b/Sources/Transactions/CoreStore+Transaction.swift
@@ -35,7 +35,7 @@ public extension CoreStore {
      
      - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
      */
-    public static func beginAsynchronous(closure: (transaction: AsynchronousDataTransaction) -> Void) {
+    public static func beginAsynchronous(_ closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
         
         self.defaultStack.beginAsynchronous(closure)
     }
@@ -46,7 +46,8 @@ public extension CoreStore {
      - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
      - returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
      */
-    public static func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
+    @discardableResult
+    public static func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
         
         return self.defaultStack.beginSynchronous(closure)
     }
@@ -57,8 +58,7 @@ public extension CoreStore {
      - prameter supportsUndo: `undo()`, `redo()`, and `rollback()` methods are only available when this parameter is `true`, otherwise those method will raise an exception. Defaults to `false`. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited.
      - returns: a `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
      */
-    @warn_unused_result
-    public static func beginUnsafe(supportsUndo supportsUndo: Bool = false) -> UnsafeDataTransaction {
+    public static func beginUnsafe(supportsUndo: Bool = false) -> UnsafeDataTransaction {
         
         return self.defaultStack.beginUnsafe(supportsUndo: supportsUndo)
     }
@@ -70,14 +70,4 @@ public extension CoreStore {
         
         self.defaultStack.refreshAndMergeAllObjects()
     }
-    
-    
-    // MARK: Deprecated
-    
-    @available(*, deprecated=1.3.1, obsoleted=2.0.0, renamed="beginUnsafe")
-    @warn_unused_result
-    public static func beginDetached() -> UnsafeDataTransaction {
-        
-        return self.beginUnsafe()
-    }
 }
diff --git a/Sources/Transactions/DataStack+Transaction.swift b/Sources/Transactions/DataStack+Transaction.swift
index 78e4e8b..310a34b 100644
--- a/Sources/Transactions/DataStack+Transaction.swift
+++ b/Sources/Transactions/DataStack+Transaction.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - DataStack
@@ -39,7 +36,7 @@ public extension DataStack {
      
      - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
      */
-    public func beginAsynchronous(closure: (transaction: AsynchronousDataTransaction) -> Void) {
+    public func beginAsynchronous(_ closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
         
         AsynchronousDataTransaction(
             mainContext: self.rootSavingContext,
@@ -53,7 +50,8 @@ public extension DataStack {
      - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
      - returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
      */
-    public func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
+    @discardableResult
+    public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
         
         return SynchronousDataTransaction(
             mainContext: self.rootSavingContext,
@@ -67,15 +65,11 @@ public extension DataStack {
      - prameter supportsUndo: `undo()`, `redo()`, and `rollback()` methods are only available when this parameter is `true`, otherwise those method will raise an exception. Defaults to `false`. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited.
      - returns: a `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
      */
-    @warn_unused_result
-    public func beginUnsafe(supportsUndo supportsUndo: Bool = false) -> UnsafeDataTransaction {
+    public func beginUnsafe(supportsUndo: Bool = false) -> UnsafeDataTransaction {
         
         return UnsafeDataTransaction(
             mainContext: self.rootSavingContext,
-            queue: .createSerial(
-                "com.coreStore.dataStack.unsafeTransactionQueue",
-                targetQueue: .UserInitiated
-            ),
+            queue: DispatchQueue.serial("com.coreStore.dataStack.unsafeTransactionQueue", qos: .userInitiated),
             supportsUndo: supportsUndo
         )
     }
@@ -86,20 +80,10 @@ public extension DataStack {
     public func refreshAndMergeAllObjects() {
         
         CoreStore.assert(
-            NSThread.isMainThread(),
+            Thread.isMainThread,
             "Attempted to refresh entities outside their designated queue."
         )
         
         self.mainContext.refreshAndMergeAllObjects()
     }
-    
-    
-    // MARK: Deprecated
-    
-    @available(*, deprecated=1.3.1, obsoleted=2.0.0, renamed="beginUnsafe")
-    @warn_unused_result
-    public func beginDetached() -> UnsafeDataTransaction {
-        
-        return self.beginUnsafe()
-    }
 }
diff --git a/Sources/Transactions/Into.swift b/Sources/Transactions/Into.swift
index 90eaa2c..cc9666f 100644
--- a/Sources/Transactions/Into.swift
+++ b/Sources/Transactions/Into.swift
@@ -32,7 +32,7 @@ import CoreData
 /**
  An `Into` clause contains the destination entity and destination persistent store for a `create(...)` method. A common usage is to just indicate the entity:
  ```
- let person = transaction.create(Into(MyPersonEntity))
+ let person = transaction.create(Into())
  ```
  For cases where multiple `NSPersistentStore`s contain the same entity, the destination configuration's name needs to be specified as well:
  ```
@@ -66,9 +66,8 @@ public struct Into: Hashable {
     /**
      Initializes an `Into` clause with the specified entity type.
      ```
-     let person = transaction.create(Into(MyPersonEntity))
+     let person = transaction.create(Into(MyPersonEntity.self))
      ```
-     
      - parameter entity: the `NSManagedObject` type to be created
      */
     public init(_ entity: T.Type) {
@@ -79,16 +78,15 @@ public struct Into: Hashable {
     /**
      Initializes an `Into` clause with the specified entity class.
      ```
-     let person = transaction.create(Into(MyPersonEntity))
+     let person = transaction.create(Into(MyPersonEntity.self))
      ```
-     
      - parameter entityClass: the `NSManagedObject` class type to be created
      */
     public init(_ entityClass: AnyClass) {
         
         CoreStore.assert(
             entityClass is T.Type,
-            "Attempted to create generic type \(cs_typeName(Into)) with entity class \(cs_typeName(entityClass))"
+            "Attempted to create generic type \(cs_typeName(Into.self)) with entity class \(cs_typeName(entityClass))"
         )
         self.init(entityClass: entityClass, configuration: nil, inferStoreIfPossible: true)
     }
@@ -98,7 +96,6 @@ public struct Into: Hashable {
      ```
      let person = transaction.create(Into("Configuration1"))
      ```
-     
      - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      */
     public init(_ configuration: String?) {
@@ -111,7 +108,6 @@ public struct Into: Hashable {
      ```
      let person = transaction.create(Into(MyPersonEntity.self, "Configuration1"))
      ```
-     
      - parameter entity: the `NSManagedObject` type to be created
      - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      */
@@ -125,7 +121,6 @@ public struct Into: Hashable {
      ```
      let person = transaction.create(Into(MyPersonEntity.self, "Configuration1"))
      ```
-     
      - parameter entityClass: the `NSManagedObject` class type to be created
      - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
      */
@@ -133,12 +128,22 @@ public struct Into: Hashable {
         
         CoreStore.assert(
             entityClass is T.Type,
-            "Attempted to create generic type \(cs_typeName(Into)) with entity class \(cs_typeName(entityClass))"
+            "Attempted to create generic type \(cs_typeName(Into.self)) with entity class \(cs_typeName(entityClass))"
         )
         self.init(entityClass: entityClass, configuration: configuration, inferStoreIfPossible: false)
     }
     
     
+    // MARK: Equatable
+    
+    public static func == (lhs: Into, rhs: Into) -> Bool {
+        
+        return lhs.entityClass == rhs.entityClass
+            && lhs.configuration == rhs.configuration
+            && lhs.inferStoreIfPossible == rhs.inferStoreIfPossible
+    }
+    
+    
     // MARK: Hashable
     
     public var hashValue: Int {
@@ -177,22 +182,3 @@ public struct Into: Hashable {
         self.inferStoreIfPossible = inferStoreIfPossible
     }
 }
-
-
-// MARK: - Into: Equatable
-
-@warn_unused_result
-public func == (lhs: Into, rhs: Into) -> Bool {
-    
-    return lhs.entityClass == rhs.entityClass
-        && lhs.configuration == rhs.configuration
-        && lhs.inferStoreIfPossible == rhs.inferStoreIfPossible
-}
-
-@warn_unused_result
-public func != (lhs: Into, rhs: Into) -> Bool {
-    
-    return lhs.entityClass == rhs.entityClass
-        && lhs.configuration == rhs.configuration
-        && lhs.inferStoreIfPossible == rhs.inferStoreIfPossible
-}
diff --git a/Sources/Transactions/NSManagedObject+Transaction.swift b/Sources/Transactions/NSManagedObject+Transaction.swift
index 9e3a23a..2ebcd73 100644
--- a/Sources/Transactions/NSManagedObject+Transaction.swift
+++ b/Sources/Transactions/NSManagedObject+Transaction.swift
@@ -48,17 +48,17 @@ public extension NSManagedObject {
     // MARK: Internal
     
     @nonobjc
-    internal class func createInContext(context: NSManagedObjectContext) -> Self {
+    internal class func createInContext(_ context: NSManagedObjectContext) -> Self {
         
         return self.init(
             entity: context.entityDescriptionForEntityType(self)!,
-            insertIntoManagedObjectContext: context
+            insertInto: context
         )
     }
     
     @nonobjc
     internal func deleteFromContext() {
         
-        self.managedObjectContext?.deleteObject(self)
+        self.managedObjectContext?.delete(self)
     }
 }
diff --git a/Sources/Transactions/SaveResult.swift b/Sources/Transactions/SaveResult.swift
index 3b0bff6..15632a5 100644
--- a/Sources/Transactions/SaveResult.swift
+++ b/Sources/Transactions/SaveResult.swift
@@ -49,9 +49,9 @@ import Foundation
      // ...
      let result = transaction.commit()
      switch result {
-     case .Success(let hasChanges):
+     case .success(let hasChanges):
         // hasChanges indicates if there were changes or not
-     case .Failure(let error):
+     case .failure(let error):
         // error is a CoreStoreError enum value
      }
  }
@@ -60,14 +60,45 @@ import Foundation
 public enum SaveResult: Hashable {
     
     /**
-     `SaveResult.Success` indicates that the `commit()` for the transaction succeeded, either because the save succeeded or because there were no changes to save. The associated value `hasChanges` indicates if there were saved changes or not.
+     `SaveResult.success` indicates that the `commit()` for the transaction succeeded, either because the save succeeded or because there were no changes to save. The associated value `hasChanges` indicates if there were saved changes or not.
      */
-    case Success(hasChanges: Bool)
+    case success(hasChanges: Bool)
     
     /**
-     `SaveResult.Failure` indicates that the `commit()` for the transaction failed. The associated object for this value is a `CoreStoreError` enum value.
+     `SaveResult.failure` indicates that the `commit()` for the transaction failed. The associated object for this value is a `CoreStoreError` enum value.
      */
-    case Failure(CoreStoreError)
+    case failure(CoreStoreError)
+    
+    
+    /**
+     Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
+     */
+    public var boolValue: Bool {
+        
+        switch self {
+            
+        case .success: return true
+        case .failure: return false
+        }
+    }
+    
+    
+    // MARK: Equatable
+    
+    public static func == (lhs: SaveResult, rhs: SaveResult) -> Bool {
+        
+        switch (lhs, rhs) {
+            
+        case (.success(let hasChanges1), .success(let hasChanges2)):
+            return hasChanges1 == hasChanges2
+            
+        case (.failure(let error1), .failure(let error2)):
+            return error1 == error2
+            
+        default:
+            return false
+        }
+    }
     
     
     // MARK: Hashable
@@ -76,10 +107,10 @@ public enum SaveResult: Hashable {
         
         switch self {
             
-        case .Success(let hasChanges):
+        case .success(let hasChanges):
             return self.boolValue.hashValue ^ hasChanges.hashValue
             
-        case .Failure(let error):
+        case .failure(let error):
             return self.boolValue.hashValue ^ error.hashValue
         }
     }
@@ -89,45 +120,11 @@ public enum SaveResult: Hashable {
     
     internal init(hasChanges: Bool) {
         
-        self = .Success(hasChanges: hasChanges)
+        self = .success(hasChanges: hasChanges)
     }
     
     internal init(_ error: CoreStoreError) {
         
-        self = .Failure(error)
-    }
-}
-
-
-// MARK: - SaveResult: BooleanType
-
-extension SaveResult: BooleanType {
-    
-    public var boolValue: Bool {
-        
-        switch self {
-            
-        case .Success: return true
-        case .Failure: return false
-        }
-    }
-}
-
-
-// MARK: - SaveResult: Equatable
-
-@warn_unused_result
-public func == (lhs: SaveResult, rhs: SaveResult) -> Bool {
-    
-    switch (lhs, rhs) {
-        
-    case (.Success(let hasChanges1), .Success(let hasChanges2)):
-        return hasChanges1 == hasChanges2
-        
-    case (.Failure(let error1), .Failure(let error2)):
-        return error1 == error2
-        
-    default:
-        return false
+        self = .failure(error)
     }
 }
diff --git a/Sources/Transactions/SynchronousDataTransaction.swift b/Sources/Transactions/SynchronousDataTransaction.swift
index df41dbc..24ed5e7 100644
--- a/Sources/Transactions/SynchronousDataTransaction.swift
+++ b/Sources/Transactions/SynchronousDataTransaction.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - SynchronousDataTransaction
@@ -46,7 +43,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
     public func commitAndWait() -> SaveResult {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to commit a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -91,10 +88,11 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
      - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
      - returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
      */
-    public func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
+    @discardableResult
+    public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
         
         CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
+            self.transactionQueue.cs_isCurrentExecutionContext(),
             "Attempted to begin a child transaction from a \(cs_typeName(self)) outside its designated queue."
         )
         CoreStore.assert(
@@ -117,11 +115,11 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
      - parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
      - returns: a new `NSManagedObject` instance of the specified entity type.
      */
-    public override func create(into: Into) -> T {
+    public override func create(_ into: Into) -> T {
         
         CoreStore.assert(
             !self.isCommitted,
-            "Attempted to create an entity of type \(cs_typeName(T)) from an already committed \(cs_typeName(self))."
+            "Attempted to create an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
         )
         
         return super.create(into)
@@ -133,8 +131,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(object: T?) -> T? {
+    public override func edit(_ object: T?) -> T? {
         
         CoreStore.assert(
             !self.isCommitted,
@@ -151,12 +148,11 @@ 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(into: Into, _ objectID: NSManagedObjectID) -> T? {
+    public override func edit(_ into: Into, _ objectID: NSManagedObjectID) -> T? {
         
         CoreStore.assert(
             !self.isCommitted,
-            "Attempted to update an entity of type \(cs_typeName(T)) from an already committed \(cs_typeName(self))."
+            "Attempted to update an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
         )
         
         return super.edit(into, objectID)
@@ -167,7 +163,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
      
      - parameter object: the `NSManagedObject` type to be deleted
      */
-    public override func delete(object: NSManagedObject?) {
+    public override func delete(_ object: NSManagedObject?) {
         
         CoreStore.assert(
             !self.isCommitted,
@@ -184,7 +180,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
      - parameter object2: another `NSManagedObject` to be deleted
      - parameter objects: other `NSManagedObject`s to be deleted
      */
-    public override func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
+    public override func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
         
         CoreStore.assert(
             !self.isCommitted,
@@ -199,7 +195,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
      
      - parameter objects: the `NSManagedObject`s to be deleted
      */
-    public override func delete(objects: S) {
+    public override func delete(_ objects: S) where S.Iterator.Element: NSManagedObject {
         
         CoreStore.assert(
             !self.isCommitted,
@@ -212,7 +208,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
     
     // MARK: Internal
     
-    internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, closure: (transaction: SynchronousDataTransaction) -> Void) {
+    internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) {
         
         self.closure = closure
         
@@ -223,12 +219,12 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
         
         self.transactionQueue.sync {
             
-            self.closure(transaction: self)
+            self.closure(self)
             
             if !self.isCommitted && self.hasChanges {
                 
                 CoreStore.log(
-                    .Warning,
+                    .warning,
                     message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
                 )
             }
@@ -239,29 +235,5 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
     
     // MARK: Private
     
-    private let closure: (transaction: SynchronousDataTransaction) -> Void
-    
-    
-    // MARK: Deprecated
-    
-    @available(*, deprecated=1.3.4, obsoleted=2.0.0, message="Resetting the context is inherently unsafe. This method will be removed in the near future. Use `beginUnsafe()` to create transactions with `undo` support.")
-    public func rollback() {
-        
-        CoreStore.assert(
-            !self.isCommitted,
-            "Attempted to rollback an already committed \(cs_typeName(self))."
-        )
-        CoreStore.assert(
-            self.transactionQueue.isCurrentExecutionContext(),
-            "Attempted to rollback a \(cs_typeName(self)) outside its designated queue."
-        )
-        
-        self.context.reset()
-    }
-    
-    @available(*, deprecated=1.5.2, obsoleted=2.0.0, renamed="commitAndWait")
-    public func commit() {
-        
-        self.commitAndWait()
-    }
+    private let closure: (_ transaction: SynchronousDataTransaction) -> Void
 }
diff --git a/Sources/Transactions/UnsafeDataTransaction.swift b/Sources/Transactions/UnsafeDataTransaction.swift
index 2af4b55..6e18f10 100644
--- a/Sources/Transactions/UnsafeDataTransaction.swift
+++ b/Sources/Transactions/UnsafeDataTransaction.swift
@@ -25,9 +25,6 @@
 
 import Foundation
 import CoreData
-#if USE_FRAMEWORKS
-    import GCDKit
-#endif
 
 
 // MARK: - UnsafeDataTransaction
@@ -42,12 +39,12 @@ public final class UnsafeDataTransaction: BaseDataTransaction {
      
      - parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block.
      */
-    public func commit(completion: (result: SaveResult) -> Void) {
+    public func commit(_ completion: @escaping (_ result: SaveResult) -> Void) {
         
         self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
             
             self.result = result
-            completion(result: result)
+            completion(result)
         }
     }
     
@@ -105,7 +102,7 @@ public final class UnsafeDataTransaction: BaseDataTransaction {
      - parameter closure: the closure where changes can be made prior to the flush
      - throws: an error thrown from `closure`, or an error thrown by Core Data (usually validation errors or conflict errors)
      */
-    public func flush(@noescape closure: () throws -> Void) rethrows {
+    public func flush(closure: () throws -> Void) rethrows {
         
         try closure()
         self.context.processPendingChanges()
@@ -129,8 +126,7 @@ public final class UnsafeDataTransaction: BaseDataTransaction {
      - prameter supportsUndo: `undo()`, `redo()`, and `rollback()` methods are only available when this parameter is `true`, otherwise those method will raise an exception. Defaults to `false`. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited.
      - returns: an `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
      */
-    @warn_unused_result
-    public func beginUnsafe(supportsUndo supportsUndo: Bool = false) -> UnsafeDataTransaction {
+    public func beginUnsafe(supportsUndo: Bool = false) -> UnsafeDataTransaction {
         
         return UnsafeDataTransaction(
             mainContext: self.context,
@@ -139,39 +135,20 @@ public final class UnsafeDataTransaction: BaseDataTransaction {
         )
     }
     
-    /**
-     Returns the `NSManagedObjectContext` for this unsafe transaction. Use only for cases where external frameworks need an `NSManagedObjectContext` instance to work with.
-     
-     - Important: It is the developer's responsibility to ensure the following:
-     - 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
-    }
-    
     
     // MARK: Internal
     
-    internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, supportsUndo: Bool) {
+    internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool) {
         
         super.init(mainContext: mainContext, queue: queue, supportsUndo: supportsUndo, bypassesQueueing: true)
     }
     
     
-    // MARK: Deprecated
+    // MARK: Obsolete
     
-    @available(*, deprecated=1.3.1, obsoleted=2.0.0, renamed="beginUnsafe")
-    @warn_unused_result
-    public func beginDetached() -> UnsafeDataTransaction {
+    @available(*, obsoleted: 3.0.0, message: "Transaction contexts are now exposed through the FetchableSource and QueryableSource protocols.", renamed: "internalContext()")
+    public var internalContext: NSManagedObjectContext {
         
-        return self.beginUnsafe()
+        fatalError()
     }
 }
-
-
-// MARK: Deprecated
-
-@available(*, deprecated=1.3.1, obsoleted=2.0.0, renamed="UnsafeDataTransaction")
-public typealias DetachedDataTransaction = UnsafeDataTransaction