From 707445a169c643dec723b42ce6e291d4e8514504 Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Fri, 25 Mar 2016 07:57:09 +0900 Subject: [PATCH] WIP: SaveResult bridge --- CoreStore.xcodeproj/project.pbxproj | 12 +++ Sources/CoreStoreError.swift | 27 ++++++- .../CSAsynchronousDataTransaction.swift | 43 ++++------- .../ObjectiveC/CSBaseDataTransaction.swift | 1 + Sources/ObjectiveC/CSDataStack.swift | 1 + Sources/ObjectiveC/CSInMemoryStore.swift | 1 + Sources/ObjectiveC/CSInto.swift | 24 +++++- Sources/ObjectiveC/CSSQliteStore.swift | 1 + Sources/ObjectiveC/CSSaveResult.swift | 76 +++++++++++++++++++ Sources/Saving and Processing/Into.swift | 26 ------- .../Saving and Processing/SaveResult.swift | 36 ++++++++- 11 files changed, 189 insertions(+), 59 deletions(-) create mode 100644 Sources/ObjectiveC/CSSaveResult.swift diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index 2720114..9f56652 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -86,6 +86,11 @@ B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; }; B5202CFA1C04688100DED140 /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; }; B5202CFD1C046E8400DED140 /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; }; + B529C2041CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */; }; + B529C2051CA4A2DB007E7EBD /* 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 */; }; @@ -464,6 +469,7 @@ B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectModel+Setup.swift"; sourceTree = ""; }; B51F25991C5747DD0083A5DD /* DataStack+iCloud.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DataStack+iCloud.swift"; sourceTree = ""; }; B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFetchedResultsController+Convenience.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; }; B546F9571C99B17400D5AC55 /* CSCoreStore+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSCoreStore+Setup.swift"; sourceTree = ""; }; @@ -782,6 +788,7 @@ B5D7A5B51CA3BF8F005C752B /* CSInto.swift */, B5519A581CA2008C002BEF78 /* CSBaseDataTransaction.swift */, B5519A5E1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift */, + B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */, ); name = "Saving and Processing"; sourceTree = ""; @@ -1278,6 +1285,7 @@ B5C976E71C6E3A5A00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */, B5F1DA901B9AA991007C5CBB /* ImportableUniqueObject.swift in Sources */, B504D0D61B02362500B2BBB1 /* CoreStore+Setup.swift in Sources */, + B529C2041CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */, B5D1E22C19FA9FBC003B2874 /* CoreStoreError.swift in Sources */, B5E84F131AFF847B0064E85B /* Where.swift in Sources */, B5D3F6451C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */, @@ -1376,6 +1384,7 @@ B5C976E81C6E3A5D00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */, 82BA18A21C4BBD1D00A0916E /* CoreStoreError.swift in Sources */, 82BA18B21C4BBD3900A0916E /* ImportableObject.swift in Sources */, + B529C2061CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */, 82BA18AE1C4BBD3100A0916E /* DataStack+Transaction.swift in Sources */, 82BA18AB1C4BBD3100A0916E /* AsynchronousDataTransaction.swift in Sources */, 82BA18CE1C4BBD7100A0916E /* FetchedResultsControllerDelegate.swift in Sources */, @@ -1507,6 +1516,7 @@ B52DD19C1BE1F92C00949AFE /* Into.swift in Sources */, B5FE4DA51C8481E100FA6A91 /* StorageInterface.swift in Sources */, B546F9711C9B14AC00D5AC55 /* CSStorageInterface.swift in Sources */, + B529C2081CA4A2DC007E7EBD /* CSSaveResult.swift in Sources */, B5FE4DAA1C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, B52DD1AF1BE1F93900949AFE /* GroupBy.swift in Sources */, B52DD1B01BE1F93900949AFE /* Tweak.swift in Sources */, @@ -1561,6 +1571,7 @@ B5C976E91C6E3A5E00B1AF90 /* CoreStoreFetchedResultsController.swift in Sources */, B56321801BD65216006C9394 /* CoreStoreError.swift in Sources */, B56321AD1BD6521C006C9394 /* MigrationManager.swift in Sources */, + B529C2071CA4A2DC007E7EBD /* CSSaveResult.swift in Sources */, B563219D1BD65216006C9394 /* DataStack+Observing.swift in Sources */, B56321961BD65216006C9394 /* From.swift in Sources */, B56321AA1BD6521C006C9394 /* AssociatedObjects.swift in Sources */, @@ -1686,6 +1697,7 @@ B5D9E3131CA2C317007A9D52 /* DataStack+Migration.swift in Sources */, B5D9E3141CA2C317007A9D52 /* BaseDataTransaction.swift in Sources */, B5D9E3151CA2C317007A9D52 /* SaveResult.swift in Sources */, + B529C2051CA4A2DB007E7EBD /* CSSaveResult.swift in Sources */, B5D9E3161CA2C317007A9D52 /* From.swift in Sources */, B5D7A5B71CA3BF8F005C752B /* CSInto.swift in Sources */, B5D9E3171CA2C317007A9D52 /* NSFileManager+Setup.swift in Sources */, diff --git a/Sources/CoreStoreError.swift b/Sources/CoreStoreError.swift index ac83067..c182054 100644 --- a/Sources/CoreStoreError.swift +++ b/Sources/CoreStoreError.swift @@ -29,7 +29,7 @@ import CoreData // MARK: - CoreStoreError -public enum CoreStoreError: ErrorType, CustomStringConvertible, CustomDebugStringConvertible, Equatable { +public enum CoreStoreError: ErrorType, CustomStringConvertible, CustomDebugStringConvertible, Hashable { /** A failure occured because of an unknown error. @@ -94,6 +94,31 @@ public enum CoreStoreError: ErrorType, CustomStringConvertible, CustomDebugStrin } + // MARK: Hashable + + public var hashValue: Int { + + let code = self._code + switch self { + + case .Unknown: + return code.hashValue + + case .DifferentStorageExistsAtURL(let existingPersistentStoreURL): + return code.hashValue ^ existingPersistentStoreURL.hashValue + + case .MappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion): + return code.hashValue ^ localStoreURL.hashValue ^ targetModel.hashValue ^ targetModelVersion.hashValue + + case .ProgressiveMigrationRequired(let localStoreURL): + return code.hashValue ^ localStoreURL.hashValue + + case .InternalError(let NSError): + return code.hashValue ^ NSError.hashValue + } + } + + // MARK: Internal internal init(_ error: ErrorType?) { diff --git a/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift b/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift index 27c8d14..4f45c9c 100644 --- a/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift +++ b/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift @@ -24,6 +24,7 @@ // import Foundation +import CoreData // MARK: - CSAsynchronousDataTransaction @@ -34,34 +35,20 @@ import Foundation @objc public final class CSAsynchronousDataTransaction: CSBaseDataTransaction { -// /** -// Saves the transaction changes. This method should not be used after the `commit()` method was already called once. -// -// - parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block. -// */ -// public func commit(completion: (result: SaveResult) -> Void = { _ in }) { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to commit a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to commit a \(typeName(self)) more than once." -// ) -// -// self.isCommitted = true -// let group = GCDGroup() -// group.enter() -// self.context.saveAsynchronouslyWithCompletion { (result) -> Void in -// -// self.result = result -// completion(result: result) -// group.leave() -// } -// group.wait() -// } -// + /** + Saves the transaction changes. This method should not be used after the `commit()` method was already called once. + + - parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block. + */ + @objc + public func commit(completion: ((result: CSSaveResult) -> Void)?) { + + self.swift.commit { (result) in + + completion?(result: result.objc) + } + } + // /** // Begins a child transaction synchronously where NSManagedObject creates, updates, and deletes can be made. This method should not be used after the `commit()` method was already called once. // diff --git a/Sources/ObjectiveC/CSBaseDataTransaction.swift b/Sources/ObjectiveC/CSBaseDataTransaction.swift index 75bb642..ab1999e 100644 --- a/Sources/ObjectiveC/CSBaseDataTransaction.swift +++ b/Sources/ObjectiveC/CSBaseDataTransaction.swift @@ -24,6 +24,7 @@ // import Foundation +import CoreData // MARK: - CSBaseDataTransaction diff --git a/Sources/ObjectiveC/CSDataStack.swift b/Sources/ObjectiveC/CSDataStack.swift index 4bb1968..bf56b00 100644 --- a/Sources/ObjectiveC/CSDataStack.swift +++ b/Sources/ObjectiveC/CSDataStack.swift @@ -255,6 +255,7 @@ public final class CSDataStack: NSObject, CoreStoreBridge { internal init(_ swiftObject: DataStack) { self.swift = swiftObject + super.init() } } diff --git a/Sources/ObjectiveC/CSInMemoryStore.swift b/Sources/ObjectiveC/CSInMemoryStore.swift index e66bd0c..d6c4362 100644 --- a/Sources/ObjectiveC/CSInMemoryStore.swift +++ b/Sources/ObjectiveC/CSInMemoryStore.swift @@ -107,6 +107,7 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreBridg public required init(_ swiftObject: InMemoryStore) { self.swift = swiftObject + super.init() } } diff --git a/Sources/ObjectiveC/CSInto.swift b/Sources/ObjectiveC/CSInto.swift index 7c4a1fa..315f2a0 100644 --- a/Sources/ObjectiveC/CSInto.swift +++ b/Sources/ObjectiveC/CSInto.swift @@ -2,11 +2,29 @@ // CSInto.swift // CoreStore // -// Created by John Estropia on 2016/03/24. -// Copyright © 2016年 John Rommel Estropia. All rights reserved. +// 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 UIKit +import Foundation +import CoreData // MARK: - CSInto diff --git a/Sources/ObjectiveC/CSSQliteStore.swift b/Sources/ObjectiveC/CSSQliteStore.swift index d17ba1b..898c177 100644 --- a/Sources/ObjectiveC/CSSQliteStore.swift +++ b/Sources/ObjectiveC/CSSQliteStore.swift @@ -184,6 +184,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreBridge { public required init(_ swiftObject: SQLiteStore) { self.swift = swiftObject + super.init() } } diff --git a/Sources/ObjectiveC/CSSaveResult.swift b/Sources/ObjectiveC/CSSaveResult.swift new file mode 100644 index 0000000..7595d60 --- /dev/null +++ b/Sources/ObjectiveC/CSSaveResult.swift @@ -0,0 +1,76 @@ +// +// CSSaveResult.swift +// CoreStore +// +// Copyright © 2016 John Rommel Estropia +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +import Foundation +import CoreData + + +// MARK: - CSSaveResult + +/** + The `CSSaveResult` serves as the Objective-C bridging type for `SaveResult`. + */ +@objc +public final class CSSaveResult: NSObject, CoreStoreBridge { + + + + // MARK: NSObject + + public override var hash: Int { + + return self.swift.hashValue + } + + public override func isEqual(object: AnyObject?) -> Bool { + + guard let object = object as? CSSaveResult else { + + return false + } + return self.swift == object.swift + } + + + // MARK: CoreStoreBridge + + internal let swift: SaveResult + + public required init(_ swiftObject: SaveResult) { + + self.swift = swiftObject + super.init() + } +} + + +// MARK: - SaveResult + +extension SaveResult: CoreStoreBridgeable { + + // MARK: CoreStoreBridgeable + + internal typealias ObjCType = CSSaveResult +} diff --git a/Sources/Saving and Processing/Into.swift b/Sources/Saving and Processing/Into.swift index 1f1a623..d44a9a2 100644 --- a/Sources/Saving and Processing/Into.swift +++ b/Sources/Saving and Processing/Into.swift @@ -148,32 +148,6 @@ public struct Into: Hashable { self.configuration = configuration self.inferStoreIfPossible = inferStoreIfPossible } - - internal func upcast() -> Into { - - return Into( - entityClass: self.entityClass, - configuration: self.configuration, - inferStoreIfPossible: self.inferStoreIfPossible - ) - } - - internal func downCast(type: U.Type) -> Into? { - - let entityClass: AnyClass = self.entityClass - guard entityClass.isSubclassOfClass(U) else { - - return nil - } - return Into( - entityClass: entityClass, - configuration: self.configuration, - inferStoreIfPossible: self.inferStoreIfPossible - ) - } - - - // MARK: Private } diff --git a/Sources/Saving and Processing/SaveResult.swift b/Sources/Saving and Processing/SaveResult.swift index 90d34ba..3b0bff6 100644 --- a/Sources/Saving and Processing/SaveResult.swift +++ b/Sources/Saving and Processing/SaveResult.swift @@ -57,7 +57,7 @@ import Foundation } ``` */ -public enum SaveResult { +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. @@ -70,6 +70,21 @@ public enum SaveResult { case Failure(CoreStoreError) + // MARK: Hashable + + public var hashValue: Int { + + switch self { + + case .Success(let hasChanges): + return self.boolValue.hashValue ^ hasChanges.hashValue + + case .Failure(let error): + return self.boolValue.hashValue ^ error.hashValue + } + } + + // MARK: Internal internal init(hasChanges: Bool) { @@ -97,3 +112,22 @@ extension SaveResult: BooleanType { } } } + + +// 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 + } +}