From 1ff635d8b521eccde891309ba69596c8c22ee0dd Mon Sep 17 00:00:00 2001 From: John Estropia Date: Fri, 25 Mar 2016 17:57:26 +0900 Subject: [PATCH] WIP: CSImportableObject --- CoreStore.xcodeproj/project.pbxproj | 54 ++++- .../CSAsynchronousDataTransaction.swift | 210 +++++++----------- .../ObjectiveC/CSBaseDataTransaction.swift | 26 ++- Sources/ObjectiveC/CSCoreStore+Setup.swift | 25 ++- Sources/ObjectiveC/CSCoreStore.swift | 3 +- Sources/ObjectiveC/CSError.swift | 3 + Sources/ObjectiveC/CSImportableObject.swift | 53 +++++ Sources/ObjectiveC/CSSQliteStore.swift | 4 +- Sources/ObjectiveC/CSSaveResult.swift | 98 ++++++++ Sources/ObjectiveC/CSStorageInterface.swift | 2 +- .../CSSynchronousDataTransaction.swift | 162 ++++++++++++++ .../ObjectiveC/CSUnsafeDataTransaction.swift | 167 ++++++++++++++ Sources/ObjectiveC/CoreStoreBridge.swift | 5 + .../UnsafeDataTransaction.swift | 6 +- 14 files changed, 670 insertions(+), 148 deletions(-) create mode 100644 Sources/ObjectiveC/CSImportableObject.swift create mode 100644 Sources/ObjectiveC/CSSynchronousDataTransaction.swift create mode 100644 Sources/ObjectiveC/CSUnsafeDataTransaction.swift diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index 9f56652..0a1b27c 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -365,6 +365,21 @@ B5DC47CA1C93D9C800FA3BF3 /* StorageInterfaceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C91C93D9C800FA3BF3 /* StorageInterfaceTests.swift */; }; B5DC47CB1C93D9C800FA3BF3 /* StorageInterfaceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C91C93D9C800FA3BF3 /* StorageInterfaceTests.swift */; }; B5DC47CC1C93D9C800FA3BF3 /* StorageInterfaceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC47C91C93D9C800FA3BF3 /* StorageInterfaceTests.swift */; }; + B5E222231CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222221CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift */; }; + B5E222241CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222221CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift */; }; + B5E222251CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222221CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift */; }; + B5E222261CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222221CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift */; }; + B5E222271CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222221CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift */; }; + B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */; }; + B5E2222B1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */; }; + B5E2222C1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */; }; + B5E2222D1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */; }; + B5E2222E1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */; }; + B5E222311CA533A400BA2E95 /* CSImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222301CA533A400BA2E95 /* CSImportableObject.swift */; }; + B5E222321CA533A400BA2E95 /* CSImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222301CA533A400BA2E95 /* CSImportableObject.swift */; }; + B5E222331CA533A400BA2E95 /* CSImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222301CA533A400BA2E95 /* CSImportableObject.swift */; }; + B5E222341CA533A400BA2E95 /* CSImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222301CA533A400BA2E95 /* CSImportableObject.swift */; }; + B5E222351CA533A400BA2E95 /* CSImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E222301CA533A400BA2E95 /* CSImportableObject.swift */; }; B5E834B91B76311F001D3D50 /* BaseDataTransaction+Importing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */; }; B5E834BB1B7691F3001D3D50 /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E834BA1B7691F3001D3D50 /* Functions.swift */; }; B5E84EDF1AFF84500064E85B /* DataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EDB1AFF84500064E85B /* DataStack.swift */; }; @@ -523,6 +538,9 @@ B5DBE2DE1C9939E100B5CEFA /* BridgingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BridgingTests.m; sourceTree = ""; }; B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationChainTests.swift; sourceTree = ""; }; B5DC47C91C93D9C800FA3BF3 /* StorageInterfaceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageInterfaceTests.swift; sourceTree = ""; }; + B5E222221CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSynchronousDataTransaction.swift; sourceTree = ""; }; + B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSUnsafeDataTransaction.swift; sourceTree = ""; }; + B5E222301CA533A400BA2E95 /* CSImportableObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSImportableObject.swift; sourceTree = ""; }; B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BaseDataTransaction+Importing.swift"; sourceTree = ""; }; B5E834BA1B7691F3001D3D50 /* Functions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Functions.swift; sourceTree = ""; }; B5E84ED81AFF82360064E85B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; @@ -788,6 +806,8 @@ B5D7A5B51CA3BF8F005C752B /* CSInto.swift */, B5519A581CA2008C002BEF78 /* CSBaseDataTransaction.swift */, B5519A5E1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift */, + B5E222221CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift */, + B5E222291CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift */, B529C2031CA4A2DB007E7EBD /* CSSaveResult.swift */, ); name = "Saving and Processing"; @@ -822,15 +842,32 @@ B5DBE2CB1C99148100B5CEFA /* ObjectiveC */ = { isa = PBXGroup; children = ( - B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */, B5DBE2CC1C9914A900B5CEFA /* CSCoreStore.swift */, B5519A491CA1F4FB002BEF78 /* CSError.swift */, + B5E2222F1CA5339200BA2E95 /* Importing Data */, B546F9611C9A13F400D5AC55 /* Setup */, B5519A5D1CA20093002BEF78 /* Saving and Processing */, + B5E222211CA4DE5700BA2E95 /* Internal */, ); path = ObjectiveC; sourceTree = ""; }; + B5E222211CA4DE5700BA2E95 /* Internal */ = { + isa = PBXGroup; + children = ( + B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */, + ); + name = Internal; + sourceTree = ""; + }; + B5E2222F1CA5339200BA2E95 /* Importing Data */ = { + isa = PBXGroup; + children = ( + B5E222301CA533A400BA2E95 /* CSImportableObject.swift */, + ); + name = "Importing Data"; + sourceTree = ""; + }; B5E834B61B7630BD001D3D50 /* Importing Data */ = { isa = PBXGroup; children = ( @@ -1337,11 +1374,14 @@ B59D5C221B5BA34B00453479 /* NSFileManager+Setup.swift in Sources */, B5FAD6A91B50A4B400714891 /* NSProgress+Convenience.swift in Sources */, B5E84EFC1AFF846E0064E85B /* SynchronousDataTransaction.swift in Sources */, + B5E222231CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, B5E84F281AFF84920064E85B /* NSManagedObject+Convenience.swift in Sources */, B51BE06A1B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift in Sources */, B5AEFAB51C9962AE00AD137F /* CoreStoreBridge.swift in Sources */, + B5E2222A1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, B5E84F391AFF85470064E85B /* NSManagedObjectContext+Querying.swift in Sources */, B5E84EE81AFF84610064E85B /* CoreStoreLogger.swift in Sources */, + B5E222311CA533A400BA2E95 /* CSImportableObject.swift in Sources */, B5E84F311AFF849C0064E85B /* WeakObject.swift in Sources */, B5E84F101AFF847B0064E85B /* GroupBy.swift in Sources */, B5E84F201AFF84860064E85B /* DataStack+Observing.swift in Sources */, @@ -1436,11 +1476,14 @@ 82BA18BF1C4BBD5300A0916E /* SectionBy.swift in Sources */, 82BA18AC1C4BBD3100A0916E /* SynchronousDataTransaction.swift in Sources */, 82BA18C71C4BBD5900A0916E /* CoreStore+Migration.swift in Sources */, + B5E222251CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, 82BA18C41C4BBD5300A0916E /* ListMonitor.swift in Sources */, 82BA18BA1C4BBD4A00A0916E /* Select.swift in Sources */, B5AEFAB61C9962AE00AD137F /* CoreStoreBridge.swift in Sources */, + B5E2222C1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, 82BA18A71C4BBD2900A0916E /* CoreStore+Logging.swift in Sources */, 82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */, + B5E222331CA533A400BA2E95 /* CSImportableObject.swift in Sources */, 82BA18AF1C4BBD3100A0916E /* CoreStore+Transaction.swift in Sources */, 82BA18CB1C4BBD6400A0916E /* NSManagedObject+Convenience.swift in Sources */, 82BA18B51C4BBD3F00A0916E /* BaseDataTransaction+Querying.swift in Sources */, @@ -1503,6 +1546,7 @@ B52DD1AD1BE1F93900949AFE /* Where.swift in Sources */, B52DD1C41BE1F94600949AFE /* NSFileManager+Setup.swift in Sources */, B52DD1AC1BE1F93900949AFE /* Select.swift in Sources */, + B5E222351CA533A400BA2E95 /* CSImportableObject.swift in Sources */, B5FE4DAF1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */, B52DD1C71BE1F94600949AFE /* NSManagedObjectContext+Querying.swift in Sources */, B52DD1C81BE1F94600949AFE /* NSManagedObjectContext+Setup.swift in Sources */, @@ -1512,6 +1556,7 @@ B52DD19D1BE1F92C00949AFE /* BaseDataTransaction.swift in Sources */, B52DD1B81BE1F94000949AFE /* DataStack+Migration.swift in Sources */, B52DD1A51BE1F92F00949AFE /* ImportableUniqueObject.swift in Sources */, + B5E222271CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, B5519A621CA21954002BEF78 /* CSAsynchronousDataTransaction.swift in Sources */, B52DD19C1BE1F92C00949AFE /* Into.swift in Sources */, B5FE4DA51C8481E100FA6A91 /* StorageInterface.swift in Sources */, @@ -1534,6 +1579,7 @@ B546F96C1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B52DD1C61BE1F94600949AFE /* NSManagedObjectContext+CoreStore.swift in Sources */, B52DD1A21BE1F92C00949AFE /* CoreStore+Transaction.swift in Sources */, + B5E2222E1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */, B52DD1BB1BE1F94000949AFE /* MigrationType.swift in Sources */, B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */, @@ -1623,11 +1669,14 @@ B56321991BD65216006C9394 /* OrderBy.swift in Sources */, B56321A51BD65216006C9394 /* MigrationChain.swift in Sources */, B563218E1BD65216006C9394 /* SaveResult.swift in Sources */, + B5E222261CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, B56321A21BD65216006C9394 /* ListObserver.swift in Sources */, B563218A1BD65216006C9394 /* SynchronousDataTransaction.swift in Sources */, B5AEFAB71C9962AE00AD137F /* CoreStoreBridge.swift in Sources */, + B5E2222D1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, B563219F1BD65216006C9394 /* ObjectMonitor.swift in Sources */, B56321B61BD6521C006C9394 /* WeakObject.swift in Sources */, + B5E222341CA533A400BA2E95 /* CSImportableObject.swift in Sources */, B56321AC1BD6521C006C9394 /* Functions.swift in Sources */, B56321851BD65216006C9394 /* CoreStore+Logging.swift in Sources */, B56321921BD65216006C9394 /* BaseDataTransaction+Querying.swift in Sources */, @@ -1653,6 +1702,7 @@ files = ( B5EA11DD1CA3AFD9002282F8 /* NSPersistentStoreCoordinator+Setup.swift in Sources */, B5D9E2EF1CA2C317007A9D52 /* ObjectMonitor.swift in Sources */, + B5E2222B1CA51B6E00BA2E95 /* CSUnsafeDataTransaction.swift in Sources */, B5D9E2F01CA2C317007A9D52 /* CoreStoreFetchedResultsController.swift in Sources */, B5D9E3461CA2C6C4007A9D52 /* GCDQueue.swift in Sources */, B5D9E2F11CA2C317007A9D52 /* ImportableUniqueObject.swift in Sources */, @@ -1693,6 +1743,7 @@ B5D9E3101CA2C317007A9D52 /* Functions.swift in Sources */, B5D9E3431CA2C6C4007A9D52 /* GCDBlock.swift in Sources */, B5D9E3111CA2C317007A9D52 /* ListMonitor.swift in Sources */, + B5E222241CA4E12600BA2E95 /* CSSynchronousDataTransaction.swift in Sources */, B5D9E3121CA2C317007A9D52 /* UnsafeDataTransaction.swift in Sources */, B5D9E3131CA2C317007A9D52 /* DataStack+Migration.swift in Sources */, B5D9E3141CA2C317007A9D52 /* BaseDataTransaction.swift in Sources */, @@ -1716,6 +1767,7 @@ B5D9E3201CA2C317007A9D52 /* DataStack+Observing.swift in Sources */, B5D9E3211CA2C317007A9D52 /* CoreStore+Transaction.swift in Sources */, B5D9E3221CA2C317007A9D52 /* NSManagedObjectContext+CoreStore.swift in Sources */, + B5E222321CA533A400BA2E95 /* CSImportableObject.swift in Sources */, B5D9E3481CA2C6C4007A9D52 /* GCDTimer.swift in Sources */, B5D9E3231CA2C317007A9D52 /* CoreStore+Observing.swift in Sources */, B5D9E3241CA2C317007A9D52 /* BaseDataTransaction+Importing.swift in Sources */, diff --git a/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift b/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift index 4f45c9c..280c66f 100644 --- a/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift +++ b/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift @@ -36,12 +36,12 @@ import CoreData public final class CSAsynchronousDataTransaction: CSBaseDataTransaction { /** - Saves the transaction changes. This method should not be used after the `commit()` method was already called once. + Saves the transaction changes. This method should not be used after the `-commitWithCompletion:` method was already called once. - parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block. */ @objc - public func commit(completion: ((result: CSSaveResult) -> Void)?) { + public func commitWithCompletion(completion: ((result: CSSaveResult) -> Void)?) { self.swift.commit { (result) in @@ -49,133 +49,93 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction { } } -// /** -// 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. -// -// - 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? { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to begin a child transaction from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to begin a child transaction from an already committed \(typeName(self))." -// ) -// -// return SynchronousDataTransaction( -// mainContext: self.context, -// queue: self.childTransactionQueue, -// closure: closure).performAndWait() -// } -// -// -// // MARK: BaseDataTransaction -// -// /** -// Creates a new `NSManagedObject` with the specified entity type. -// -// - parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration -// - returns: a new `NSManagedObject` instance of the specified entity type. -// */ -// public override func create(into: Into) -> T { -// -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to create an entity of type \(typeName(T)) from an already committed \(typeName(self))." -// ) -// -// return super.create(into) -// } -// -// /** -// Returns an editable proxy of a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once. -// -// - 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? { -// -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to update an entity of type \(typeName(object)) from an already committed \(typeName(self))." -// ) -// -// return super.edit(object) -// } -// -// /** -// Returns an editable proxy of the object with the specified `NSManagedObjectID`. This method should not be used after the `commit()` method was already called once. -// -// - parameter into: an `Into` clause specifying the entity type -// - parameter objectID: the `NSManagedObjectID` for the object to be edited -// - returns: an editable proxy for the specified `NSManagedObject`. -// */ -// @warn_unused_result -// public override func edit(into: Into, _ objectID: NSManagedObjectID) -> T? { -// -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to update an entity of type \(typeName(T)) from an already committed \(typeName(self))." -// ) -// -// return super.edit(into, objectID) -// } -// -// /** -// Deletes a specified `NSManagedObject`. This method should not be used after the `commit()` method was already called once. -// -// - parameter object: the `NSManagedObject` type to be deleted -// */ -// public override func delete(object: NSManagedObject?) { -// -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to delete an entity of type \(typeName(object)) from an already committed \(typeName(self))." -// ) -// -// super.delete(object) -// } -// -// /** -// Deletes the specified `NSManagedObject`s. -// -// - parameter object1: the `NSManagedObject` type to be deleted -// - 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?...) { -// -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to delete an entities from an already committed \(typeName(self))." -// ) -// -// super.delete(([object1, object2] + objects).flatMap { $0 }) -// } -// -// /** -// Deletes the specified `NSManagedObject`s. -// -// - parameter objects: the `NSManagedObject`s type to be deleted -// */ -// public override func delete(objects: S) { -// -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to delete an entities from an already committed \(typeName(self))." -// ) -// -// super.delete(objects) - // } + /** + Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitWithCompletion:` method was already called once. + + - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. + - returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously + */ + @objc + public func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? { + + return bridge { + + self.swift.beginSynchronous { (transaction) in + + closure(transaction: transaction.objc) + } + } + } + + + // MARK: BaseDataTransaction + + /** + Creates a new `NSManagedObject` with the specified entity type. + + - parameter into: the `CSInto` clause indicating the destination `NSManagedObject` entity type and the destination configuration + - returns: a new `NSManagedObject` instance of the specified entity type. + */ + @objc + public override func createInto(into: CSInto) -> NSManagedObject { + + return self.swift.create(into.swift) + } + + /** + Returns an editable proxy of a specified `NSManagedObject`. This method should not be used after the `-commitWithCompletion:` method was already called once. + + - parameter object: the `NSManagedObject` type to be edited + - returns: an editable proxy for the specified `NSManagedObject`. + */ + @objc + @warn_unused_result + public override func editObject(object: NSManagedObject?) -> NSManagedObject? { + + return self.swift.edit(object) + } + + /** + Returns an editable proxy of the object with the specified `NSManagedObjectID`. This method should not be used after the `-commitWithCompletion:` method was already called once. + + - parameter into: a `CSInto` clause specifying the entity type + - parameter objectID: the `NSManagedObjectID` for the object to be edited + - returns: an editable proxy for the specified `NSManagedObject`. + */ + @objc + @warn_unused_result + public override func editInto(into: CSInto, objectID: NSManagedObjectID) -> NSManagedObject? { + + return self.swift.edit(into.swift, objectID) + } + + /** + Deletes a specified `NSManagedObject`. This method should not be used after the `-commitWithCompletion:` method was already called once. + + - parameter object: the `NSManagedObject` type to be deleted + */ + @objc + public override func deleteObject(object: NSManagedObject?) { + + self.swift.delete(object) + } + + /** + Deletes the specified `NSManagedObject`s. + + - parameter objects: the `NSManagedObject`s type to be deleted + */ + @objc + public override func deleteObjects(objects: [NSManagedObject]) { + + self.swift.delete(objects) + } // MARK: CoreStoreBridge + internal typealias SwiftType = AsynchronousDataTransaction + internal override var swift: AsynchronousDataTransaction { return super.swift as! AsynchronousDataTransaction diff --git a/Sources/ObjectiveC/CSBaseDataTransaction.swift b/Sources/ObjectiveC/CSBaseDataTransaction.swift index ab1999e..b8329ea 100644 --- a/Sources/ObjectiveC/CSBaseDataTransaction.swift +++ b/Sources/ObjectiveC/CSBaseDataTransaction.swift @@ -120,7 +120,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { // MARK: Inspecting Pending Objects /** - Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `-commit*:` method was called. - returns: an `NSSet` of pending `NSManagedObject`s that were inserted to the transaction. */ @@ -132,7 +132,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `-commit*:` method was called. - parameter entity: the `NSManagedObject` subclass to filter - returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were inserted to the transaction. @@ -145,7 +145,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObjectID`s that were inserted to the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObjectID`s that were inserted to the transaction. This method should not be called after the `-commit*:` method was called. - returns: an `NSSet` of pending `NSManagedObjectID`s that were inserted to the transaction. */ @@ -157,7 +157,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `-commit*:` method was called. - parameter entity: the `NSManagedObject` subclass to filter - returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. @@ -170,7 +170,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObject`s that were updated in the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObject`s that were updated in the transaction. This method should not be called after the `-commit*:` method was called. - returns: an `NSSet` of pending `NSManagedObject`s that were updated to the transaction. */ @@ -182,7 +182,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObject`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObject`s of the specified type that were updated in the transaction. This method should not be called after the `-commit*:` method was called. - parameter entity: the `NSManagedObject` subclass to filter - returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were updated in the transaction. @@ -195,7 +195,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObjectID`s that were updated in the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObjectID`s that were updated in the transaction. This method should not be called after the `-commit*:` method was called. - returns: an `NSSet` of pending `NSManagedObjectID`s that were updated in the transaction. */ @@ -207,7 +207,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `-commit*:` method was called. - parameter entity: the `NSManagedObject` subclass to filter - returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction. @@ -220,7 +220,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObject`s that were deleted from the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObject`s that were deleted from the transaction. This method should not be called after the `-commit*:` method was called. - returns: an `NSSet` of pending `NSManagedObject`s that were deleted from the transaction. */ @@ -232,7 +232,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObject`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObject`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called. - parameter entity: the `NSManagedObject` subclass to filter - returns: an `NSSet` of pending `NSManagedObject`s of the specified type that were deleted from the transaction. @@ -245,7 +245,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called. - parameter entity: the `NSManagedObject` subclass to filter - returns: an `NSSet` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. @@ -258,7 +258,7 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { } /** - Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called. + Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `-commit*:` method was called. - parameter entity: the `NSManagedObject` subclass to filter - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. @@ -290,6 +290,8 @@ public class CSBaseDataTransaction: NSObject, CoreStoreBridge { // MARK: CoreStoreBridge + internal typealias SwiftType = BaseDataTransaction + public required init(_ swiftObject: BaseDataTransaction) { self.swiftObject = swiftObject diff --git a/Sources/ObjectiveC/CSCoreStore+Setup.swift b/Sources/ObjectiveC/CSCoreStore+Setup.swift index d1b654a..06fbc27 100644 --- a/Sources/ObjectiveC/CSCoreStore+Setup.swift +++ b/Sources/ObjectiveC/CSCoreStore+Setup.swift @@ -2,11 +2,32 @@ // CSCoreStore+Setup.swift // CoreStore // -// Created by John Rommel Estropia on 2016/03/17. -// 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 Foundation +import CoreData + + +// MARK: - CSCoreStore public extension CSCoreStore { diff --git a/Sources/ObjectiveC/CSCoreStore.swift b/Sources/ObjectiveC/CSCoreStore.swift index a38b7a3..d817676 100644 --- a/Sources/ObjectiveC/CSCoreStore.swift +++ b/Sources/ObjectiveC/CSCoreStore.swift @@ -24,7 +24,6 @@ // import Foundation -import CoreData // MARK: - CSCoreStore @@ -38,7 +37,7 @@ public final class CSCoreStore: NSObject { /** The default `CSDataStack` instance to be used. If `defaultStack` is not set before the first time accessed, a default-configured `DataStack` will be created. - Changing the `defaultStack` is thread safe, but it is recommended to setup `DataStacks` on a common queue (e.g. the main queue). + Changing the `defaultStack` is thread safe, but it is recommended to setup stacks on a common queue (e.g. the main queue). */ @objc public class var defaultStack: CSDataStack { diff --git a/Sources/ObjectiveC/CSError.swift b/Sources/ObjectiveC/CSError.swift index 8e5aa3e..cf41d03 100644 --- a/Sources/ObjectiveC/CSError.swift +++ b/Sources/ObjectiveC/CSError.swift @@ -23,6 +23,9 @@ // SOFTWARE. // +import Foundation +import CoreData + // MARK: - CSError diff --git a/Sources/ObjectiveC/CSImportableObject.swift b/Sources/ObjectiveC/CSImportableObject.swift new file mode 100644 index 0000000..bb2d406 --- /dev/null +++ b/Sources/ObjectiveC/CSImportableObject.swift @@ -0,0 +1,53 @@ +// +// CSImportableObject.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: - CSImportableObject + +@objc +public protocol CSImportableObject: class, AnyObject { + + /** + Return `true` if an object should be created from `source`. Return `false` to ignore and skip `source`. The default implementation returns `true`. + + - parameter source: the object to import from + - parameter transaction: the transaction that invoked the import. Use the transaction to fetch or create related objects if needed. + - returns: `true` if an object should be created from `source`. Return `false` to ignore. + */ + @objc + static func shouldInsertFromImportSource(source: AnyObject, inTransaction transaction: CSBaseDataTransaction) -> 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. + */ + @objc + func didInsertFromImportSource(source: AnyObject, inTransaction transaction: CSBaseDataTransaction) throws +} diff --git a/Sources/ObjectiveC/CSSQliteStore.swift b/Sources/ObjectiveC/CSSQliteStore.swift index 898c177..0c7f7f4 100644 --- a/Sources/ObjectiveC/CSSQliteStore.swift +++ b/Sources/ObjectiveC/CSSQliteStore.swift @@ -36,7 +36,7 @@ import CoreData public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreBridge { /** - Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `addStorage()` methods, a new SQLite file will be created if it does not exist. + Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist. - parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them. - parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them. @@ -57,7 +57,7 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreBridge { } /** - Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `addStorage()` methods, a new SQLite file will be created if it does not exist. + Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist. - Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`. - parameter fileName: the local filename for the SQLite persistent store in the "Application Support/" directory (or the "Caches/" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them. diff --git a/Sources/ObjectiveC/CSSaveResult.swift b/Sources/ObjectiveC/CSSaveResult.swift index 7595d60..104f636 100644 --- a/Sources/ObjectiveC/CSSaveResult.swift +++ b/Sources/ObjectiveC/CSSaveResult.swift @@ -35,6 +35,104 @@ import CoreData @objc public final class CSSaveResult: NSObject, CoreStoreBridge { + /** + `true` if the `commit` operation for the transaction succeeded, either because the save succeeded or because there were no changes to save. Returns `false` to indicate failure. + */ + @objc + public var isSuccess: Bool { + + return self.swift.boolValue + } + + /** + `true` if the `commit` operation for the transaction failed, or `false` otherwise. When `true`, the `error` property returns the actual `NSError` for the failure. + */ + @objc + public var isFailure: Bool { + + return !self.swift.boolValue + } + + /** + `true` if the `commit` operation for the transaction succeeded and if there was an actual change made. Returns `false` otherwise. + */ + @objc + public var hasChanges: Bool { + + guard case .Success(let hasChanges) = self.swift else { + + return false + } + return hasChanges + } + + /** + The `NSError` for a failed `commit` operation, or `nil` if the `commit` succeeded + */ + @objc + public var error: NSError? { + + guard case .Failure(let error) = self.swift else { + + return nil + } + return error.objc + } + + /** + If the result was a success, the `success` block is executed with a `BOOL` argument that indicates if there were any changes made. If the result was a failure, the `failure` block is executed with an `NSError` argument pertaining to the actual error. + + The blocks are executed immediately as `@noescape` and will not be retained. + + - parameter success: the block to execute on success. The block passes a `BOOL` argument that indicates if there were any changes made. + - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actuall error. + */ + @objc + public func handleSuccess(@noescape success: (hasChanges: Bool) -> Void, @noescape failure: (error: NSError) -> Void) { + + switch self.swift { + + case .Success(let hasChanges): + success(hasChanges: hasChanges) + + case .Failure(let error): + failure(error: error.objc) + } + } + + /** + If the result was a success, the `success` block is executed with a `BOOL` argument that indicates if there were any changes made. If the result was a failure, this method does nothing. + + The block is executed immediately as `@noescape` and will not be retained. + + - 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) { + + guard case .Success(let hasChanges) = self.swift else { + + return + } + success(hasChanges: hasChanges) + } + + /** + If the result was a failure, the `failure` block is executed with an `NSError` argument pertaining to the actual error. If the result was a success, this method does nothing. + + The block is executed immediately as `@noescape` and will not be retained. + + - parameter failure: the block to execute on failure. The block passes an `NSError` argument that pertains to the actuall error. + */ + @objc + public func handleFailure(@noescape failure: (error: NSError) -> Void) { + + guard case .Failure(let error) = self.swift else { + + return + } + failure(error: error.objc) + } // MARK: NSObject diff --git a/Sources/ObjectiveC/CSStorageInterface.swift b/Sources/ObjectiveC/CSStorageInterface.swift index b590ddb..e0df8ac 100644 --- a/Sources/ObjectiveC/CSStorageInterface.swift +++ b/Sources/ObjectiveC/CSStorageInterface.swift @@ -97,7 +97,7 @@ public protocol CSLocalStorage: CSStorageInterface { var mappingModelBundles: [NSBundle] { get } /** - Options that tell the `DataStack` how to setup the persistent store + Options that tell the `CSDataStack` how to setup the persistent store */ @objc var localStorageOptions: Int { get } diff --git a/Sources/ObjectiveC/CSSynchronousDataTransaction.swift b/Sources/ObjectiveC/CSSynchronousDataTransaction.swift new file mode 100644 index 0000000..0a396fc --- /dev/null +++ b/Sources/ObjectiveC/CSSynchronousDataTransaction.swift @@ -0,0 +1,162 @@ +// +// CSSynchronousDataTransaction.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: - CSSynchronousDataTransaction + +/** + The `CSSynchronousDataTransaction` serves as the Objective-C bridging type for `SynchronousDataTransaction`. + */ +@objc +public final class CSSynchronousDataTransaction: CSBaseDataTransaction { + + /** + Saves the transaction changes and waits for completion synchronously. This method should not be used after the `-commitAndWait` method was already called once. + + - returns: a `CSSaveResult` containing the success or failure information + */ + @objc + public func commitAndWait() -> CSSaveResult { + + return bridge { + + self.swift.commitAndWait() + } + } + + /** + Begins a child transaction synchronously where `NSManagedObject` creates, updates, and deletes can be made. This method should not be used after the `-commitAndWait` method was already called once. + + - parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. + - returns: a `CSSaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously + */ + @objc + public func beginSynchronous(closure: (transaction: CSSynchronousDataTransaction) -> Void) -> CSSaveResult? { + + return bridge { + + self.swift.beginSynchronous { (transaction) in + + closure(transaction: transaction.objc) + } + } + } + + + // MARK: BaseDataTransaction + + /** + Creates a new `NSManagedObject` with the specified entity type. + + - parameter into: the `CSInto` clause indicating the destination `NSManagedObject` entity type and the destination configuration + - returns: a new `NSManagedObject` instance of the specified entity type. + */ + @objc + public override func createInto(into: CSInto) -> NSManagedObject { + + return self.swift.create(into.swift) + } + + /** + Returns an editable proxy of a specified `NSManagedObject`. This method should not be used after the `-commitAndWait` method was already called once. + + - parameter object: the `NSManagedObject` type to be edited + - returns: an editable proxy for the specified `NSManagedObject`. + */ + @objc + @warn_unused_result + public override func editObject(object: NSManagedObject?) -> NSManagedObject? { + + return self.swift.edit(object) + } + + /** + Returns an editable proxy of the object with the specified `NSManagedObjectID`. This method should not be used after the `-commitAndWait` method was already called once. + + - parameter into: a `CSInto` clause specifying the entity type + - parameter objectID: the `NSManagedObjectID` for the object to be edited + - returns: an editable proxy for the specified `NSManagedObject`. + */ + @objc + @warn_unused_result + public override func editInto(into: CSInto, objectID: NSManagedObjectID) -> NSManagedObject? { + + return self.swift.edit(into.swift, objectID) + } + + /** + Deletes a specified `NSManagedObject`. This method should not be used after the `-commitAndWait` method was already called once. + + - parameter object: the `NSManagedObject` type to be deleted + */ + @objc + public override func deleteObject(object: NSManagedObject?) { + + return self.swift.delete(object) + } + + /** + Deletes the specified `NSManagedObject`s. + + - parameter objects: the `NSManagedObject`s to be deleted + */ + public override func deleteObjects(objects: [NSManagedObject]) { + + self.swift.delete(objects) + } + + + // MARK: CoreStoreBridge + + internal typealias SwiftType = SynchronousDataTransaction + + internal override var swift: SynchronousDataTransaction { + + return super.swift as! SynchronousDataTransaction + } + + public required init(_ swiftObject: SynchronousDataTransaction) { + + super.init(swiftObject) + } + + required public init(_ swiftObject: BaseDataTransaction) { + + fatalError("init has not been implemented") + } +} + + +// MARK: - SynchronousDataTransaction + +extension SynchronousDataTransaction { + + // MARK: CoreStoreBridgeable + + internal typealias ObjCType = CSSynchronousDataTransaction +} diff --git a/Sources/ObjectiveC/CSUnsafeDataTransaction.swift b/Sources/ObjectiveC/CSUnsafeDataTransaction.swift new file mode 100644 index 0000000..30a65b1 --- /dev/null +++ b/Sources/ObjectiveC/CSUnsafeDataTransaction.swift @@ -0,0 +1,167 @@ +// +// CSUnsafeDataTransaction.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: - CSUnsafeDataTransaction + +/** + The `CSUnsafeDataTransaction` serves as the Objective-C bridging type for `UnsafeDataTransaction`. + */ +@objc +public final class CSUnsafeDataTransaction: CSBaseDataTransaction { + + /** + Saves the transaction changes asynchronously. For a `CSUnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread. + + - parameter completion: the block executed after the save completes. Success or failure is reported by the `CSSaveResult` argument of the block. + */ + @objc + public func commit(completion: ((result: CSSaveResult) -> Void)?) { + + self.swift.commit { (result) in + + completion?(result: result.objc) + } + } + + /** + Saves the transaction changes and waits for completion synchronously. For a `CSUnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread. + + - returns: a `CSSaveResult` containing the success or failure information + */ + @objc + public func commitAndWait() -> CSSaveResult { + + return bridge { + + self.swift.commitAndWait() + } + } + + /** + Rolls back the transaction. + */ + @objc + public func rollback() { + + self.swift.rollback() + } + + /** + Undo's the last change made to the transaction. + */ + @objc + public func undo() { + + self.swift.undo() + } + + /** + Redo's the last undone change to the transaction. + */ + @objc + public func redo() { + + self.swift.redo() + } + + /** + Begins a child transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms. + + To support "undo" methods such as `-undo`, `-redo`, and `-rollback`, use the `-beginSafeWithSupportsUndo:` method passing `true` to the argument. Without "undo" support, calling those methods will raise an exception. + - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made. + */ + @objc + @warn_unused_result + public func beginUnsafe() -> CSUnsafeDataTransaction { + + return bridge { + + self.swift.beginUnsafe() + } + } + + /** + Begins a child transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms. + + - prameter supportsUndo: `-undo`, `-redo`, and `-rollback` methods are only available when this parameter is `true`, otherwise those method will raise an exception. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited. + - returns: a `CSUnsafeDataTransaction` instance where creates, updates, and deletes can be made. + */ + @objc + @warn_unused_result + public func beginUnsafeWithSupportsUndo(supportsUndo: Bool) -> CSUnsafeDataTransaction { + + return bridge { + + self.swift.beginUnsafe(supportsUndo: supportsUndo) + } + } + + /** + Returns the `NSManagedObjectContext` for this unsafe transaction. Use only for cases where external frameworks need an `NSManagedObjectContext` instance to work with. + + Note that it is the developer's responsibility to ensure the following: + - that the `CSUnsafeDataTransaction` 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 `CSUnsafeDataTransaction`'s `-commit:` or `-commitAndWait` method, or by calling `-save:` manually on the context, its parent, and all other ancestor contexts if there are any. + */ + @objc + public var internalContext: NSManagedObjectContext { + + return self.swift.context + } + + + // MARK: CoreStoreBridge + + internal typealias SwiftType = UnsafeDataTransaction + + internal override var swift: UnsafeDataTransaction { + + return super.swift as! UnsafeDataTransaction + } + + public required init(_ swiftObject: UnsafeDataTransaction) { + + super.init(swiftObject) + } + + required public init(_ swiftObject: BaseDataTransaction) { + + fatalError("init has not been implemented") + } +} + + +// MARK: - UnsafeDataTransaction + +extension UnsafeDataTransaction { + + // MARK: CoreStoreBridgeable + + internal typealias ObjCType = CSUnsafeDataTransaction +} diff --git a/Sources/ObjectiveC/CoreStoreBridge.swift b/Sources/ObjectiveC/CoreStoreBridge.swift index 96a55d1..0a1697e 100644 --- a/Sources/ObjectiveC/CoreStoreBridge.swift +++ b/Sources/ObjectiveC/CoreStoreBridge.swift @@ -63,6 +63,11 @@ internal func bridge(@no return closure().objc } +internal func bridge(@noescape closure: () -> T?) -> T.ObjCType? { + + return closure()?.objc +} + internal func bridge(@noescape closure: () throws -> T) throws -> T.ObjCType { do { diff --git a/Sources/Saving and Processing/UnsafeDataTransaction.swift b/Sources/Saving and Processing/UnsafeDataTransaction.swift index 5a08a44..e12eacf 100644 --- a/Sources/Saving and Processing/UnsafeDataTransaction.swift +++ b/Sources/Saving and Processing/UnsafeDataTransaction.swift @@ -38,7 +38,7 @@ import CoreData public final class UnsafeDataTransaction: BaseDataTransaction { /** - Saves the transaction changes asynchronously. For a `UnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread. + Saves the transaction changes asynchronously. For an `UnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread. - parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block. */ @@ -52,7 +52,7 @@ public final class UnsafeDataTransaction: BaseDataTransaction { } /** - Saves the transaction changes and waits for completion synchronously. For a `UnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread. + Saves the transaction changes and waits for completion synchronously. For an `UnsafeDataTransaction`, multiple commits are allowed, although it is the developer's responsibility to ensure a reasonable leeway to prevent blocking the main thread. - returns: a `SaveResult` containing the success or failure information */ @@ -103,7 +103,7 @@ public final class UnsafeDataTransaction: BaseDataTransaction { Begins a child transaction where `NSManagedObject` creates, updates, and deletes can be made. This is useful for making temporary changes, such as partially filled forms. - 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. + - returns: an `UnsafeDataTransaction` instance where creates, updates, and deletes can be made. */ @warn_unused_result public func beginUnsafe(supportsUndo supportsUndo: Bool = false) -> UnsafeDataTransaction {