diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index 21b5dc7..2720114 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -264,12 +264,17 @@ B5D3F6471C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D3F6441C887C0A00C7492A /* LegacySQLiteStore.swift */; }; B5D3F6481C887C0A00C7492A /* LegacySQLiteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D3F6441C887C0A00C7492A /* LegacySQLiteStore.swift */; }; B5D5E0CF1A4D6AAB006468AF /* TestEntity2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D5E0CE1A4D6AAB006468AF /* TestEntity2.swift */; }; - B5D7A5AF1CA3B738005C752B /* LocalStorageOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B546F9521C95529D00D5AC55 /* LocalStorageOptions.swift */; }; + B5D7A5AF1CA3B738005C752B /* (null) in Sources */ = {isa = PBXBuildFile; }; B5D7A5B01CA3B738005C752B /* StorageInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FE4DA11C8481E100FA6A91 /* StorageInterface.swift */; }; B5D7A5B11CA3B738005C752B /* InMemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FE4DA61C84FB4400FA6A91 /* InMemoryStore.swift */; }; B5D7A5B21CA3B738005C752B /* SQLiteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FE4DAB1C85D44E00FA6A91 /* SQLiteStore.swift */; }; B5D7A5B31CA3B738005C752B /* LegacySQLiteStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D3F6441C887C0A00C7492A /* LegacySQLiteStore.swift */; }; B5D7A5B41CA3BAE7005C752B /* NSPersistentStore+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FEC18D1C9166E200532541 /* NSPersistentStore+Setup.swift */; }; + B5D7A5B61CA3BF8F005C752B /* CSInto.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D7A5B51CA3BF8F005C752B /* CSInto.swift */; }; + B5D7A5B71CA3BF8F005C752B /* CSInto.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D7A5B51CA3BF8F005C752B /* CSInto.swift */; }; + B5D7A5B81CA3BF8F005C752B /* CSInto.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D7A5B51CA3BF8F005C752B /* CSInto.swift */; }; + B5D7A5B91CA3BF8F005C752B /* CSInto.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D7A5B51CA3BF8F005C752B /* CSInto.swift */; }; + B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D7A5B51CA3BF8F005C752B /* CSInto.swift */; }; B5D9E2EF1CA2C317007A9D52 /* ObjectMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F1C1AFF84860064E85B /* ObjectMonitor.swift */; }; B5D9E2F01CA2C317007A9D52 /* CoreStoreFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C976E61C6E3A5900B1AF90 /* CoreStoreFetchedResultsController.swift */; }; B5D9E2F11CA2C317007A9D52 /* ImportableUniqueObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */; }; @@ -292,7 +297,7 @@ B5D9E3021CA2C317007A9D52 /* Select.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F031AFF847B0064E85B /* Select.swift */; }; B5D9E3031CA2C317007A9D52 /* NSManagedObject+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50392F81C478FF3009900CA /* NSManagedObject+Transaction.swift */; }; B5D9E3041CA2C317007A9D52 /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; }; - B5D9E3051CA2C317007A9D52 /* SetupResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84EDE1AFF84500064E85B /* SetupResult.swift */; }; + B5D9E3051CA2C317007A9D52 /* (null) in Sources */ = {isa = PBXBuildFile; }; B5D9E3061CA2C317007A9D52 /* ObjectObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F1F1AFF84860064E85B /* ObjectObserver.swift */; }; B5D9E3071CA2C317007A9D52 /* NotificationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2B1AFF849C0064E85B /* NotificationObserver.swift */; }; B5D9E3081CA2C317007A9D52 /* ImportableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */; }; @@ -496,6 +501,7 @@ B5D39A0119FD00C9000E91BB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; B5D3F6441C887C0A00C7492A /* LegacySQLiteStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacySQLiteStore.swift; sourceTree = ""; }; B5D5E0CE1A4D6AAB006468AF /* TestEntity2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestEntity2.swift; sourceTree = ""; }; + B5D7A5B51CA3BF8F005C752B /* CSInto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSInto.swift; sourceTree = ""; }; B5D9C8F61B160ED200E64F0E /* CoreStore.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = CoreStore.podspec; sourceTree = SOURCE_ROOT; }; B5D9E3341CA2C317007A9D52 /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B5D9E3371CA2C6BF007A9D52 /* GCDBlock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GCDBlock.swift; path = Carthage/Checkouts/GCDKit/Sources/GCDBlock.swift; sourceTree = ""; }; @@ -711,7 +717,6 @@ B5D372851A39CDDB00F583D9 /* TestEntity1.swift */, B5D5E0CE1A4D6AAB006468AF /* TestEntity2.swift */, 2F03A53D19C5C6DA005002A5 /* Supporting Files */, - B5DBE2DA1C9939E100B5CEFA /* CoreStoreTests-Bridging-Header.h */, ); path = CoreStoreTests; sourceTree = ""; @@ -721,6 +726,7 @@ children = ( B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */, 2F03A53E19C5C6DA005002A5 /* Info.plist */, + B5DBE2DA1C9939E100B5CEFA /* CoreStoreTests-Bridging-Header.h */, ); name = "Supporting Files"; sourceTree = ""; @@ -773,6 +779,7 @@ B5519A5D1CA20093002BEF78 /* Saving and Processing */ = { isa = PBXGroup; children = ( + B5D7A5B51CA3BF8F005C752B /* CSInto.swift */, B5519A581CA2008C002BEF78 /* CSBaseDataTransaction.swift */, B5519A5E1CA21954002BEF78 /* CSAsynchronousDataTransaction.swift */, ); @@ -1278,6 +1285,7 @@ B54A6A551BA15F2A007870FD /* FetchedResultsControllerDelegate.swift in Sources */, B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */, B5E84F141AFF847B0064E85B /* DataStack+Querying.swift in Sources */, + B5D7A5B61CA3BF8F005C752B /* CSInto.swift in Sources */, B56007141B3F6C2800A9A8F9 /* SectionBy.swift in Sources */, B5E84F371AFF85470064E85B /* NSManagedObjectContext+Transaction.swift in Sources */, B5C976E31C6C9F6A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, @@ -1375,6 +1383,7 @@ B5FE4DAD1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */, 82BA18C51C4BBD5300A0916E /* ListObserver.swift in Sources */, 82BA18C21C4BBD5300A0916E /* ObjectMonitor.swift in Sources */, + B5D7A5B81CA3BF8F005C752B /* CSInto.swift in Sources */, 82BA18A51C4BBD2200A0916E /* CoreStore+Setup.swift in Sources */, 82BA18BD1C4BBD4A00A0916E /* GroupBy.swift in Sources */, B5C976E41C6C9F9A00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, @@ -1467,6 +1476,7 @@ B52DD1951BE1F92500949AFE /* CoreStoreError.swift in Sources */, B546F9601C9A12B800D5AC55 /* CSSQliteStore.swift in Sources */, B52DD1C21BE1F94600949AFE /* MigrationManager.swift in Sources */, + B5D7A5BA1CA3BF8F005C752B /* CSInto.swift in Sources */, B5FEC1911C9166E700532541 /* NSPersistentStore+Setup.swift in Sources */, B52DD1AB1BE1F93900949AFE /* From.swift in Sources */, B52DD1BF1BE1F94600949AFE /* AssociatedObjects.swift in Sources */, @@ -1558,6 +1568,7 @@ B5FE4DAE1C85D44E00FA6A91 /* SQLiteStore.swift in Sources */, B563218C1BD65216006C9394 /* DataStack+Transaction.swift in Sources */, B563219E1BD65216006C9394 /* CoreStore+Observing.swift in Sources */, + B5D7A5B91CA3BF8F005C752B /* CSInto.swift in Sources */, B56321891BD65216006C9394 /* AsynchronousDataTransaction.swift in Sources */, B56321831BD65216006C9394 /* CoreStore+Setup.swift in Sources */, B5C976E51C6C9F9B00B1AF90 /* UnsafeDataTransaction+Observing.swift in Sources */, @@ -1636,7 +1647,7 @@ B5D9E2F11CA2C317007A9D52 /* ImportableUniqueObject.swift in Sources */, B5D9E2F21CA2C317007A9D52 /* CoreStore+Setup.swift in Sources */, B5D7A5B31CA3B738005C752B /* LegacySQLiteStore.swift in Sources */, - B5D7A5AF1CA3B738005C752B /* LocalStorageOptions.swift in Sources */, + B5D7A5AF1CA3B738005C752B /* (null) in Sources */, B5D7A5B11CA3B738005C752B /* InMemoryStore.swift in Sources */, B5D9E2F31CA2C317007A9D52 /* CoreStoreError.swift in Sources */, B5D9E2F41CA2C317007A9D52 /* Where.swift in Sources */, @@ -1657,7 +1668,7 @@ B5D7A5B41CA3BAE7005C752B /* NSPersistentStore+Setup.swift in Sources */, B5D9E3031CA2C317007A9D52 /* NSManagedObject+Transaction.swift in Sources */, B5D9E3041CA2C317007A9D52 /* NSFetchedResultsController+Convenience.swift in Sources */, - B5D9E3051CA2C317007A9D52 /* SetupResult.swift in Sources */, + B5D9E3051CA2C317007A9D52 /* (null) in Sources */, B5D9E3061CA2C317007A9D52 /* ObjectObserver.swift in Sources */, B5D9E3071CA2C317007A9D52 /* NotificationObserver.swift in Sources */, B5D9E3081CA2C317007A9D52 /* ImportableObject.swift in Sources */, @@ -1676,6 +1687,7 @@ B5D9E3141CA2C317007A9D52 /* BaseDataTransaction.swift in Sources */, B5D9E3151CA2C317007A9D52 /* SaveResult.swift in Sources */, B5D9E3161CA2C317007A9D52 /* From.swift in Sources */, + B5D7A5B71CA3BF8F005C752B /* CSInto.swift in Sources */, B5D9E3171CA2C317007A9D52 /* NSFileManager+Setup.swift in Sources */, B5D9E3181CA2C317007A9D52 /* NSProgress+Convenience.swift in Sources */, B5D9E3191CA2C317007A9D52 /* SynchronousDataTransaction.swift in Sources */, diff --git a/Sources/CoreStoreError.swift b/Sources/CoreStoreError.swift index 9b38b1e..ac83067 100644 --- a/Sources/CoreStoreError.swift +++ b/Sources/CoreStoreError.swift @@ -203,114 +203,3 @@ public extension NSError { : nil) } } - - -// MARK: Internal - -internal extension ErrorType { - - internal var swift: CoreStoreError { - - if case let error as CoreStoreError = self { - - return error - } - - guard let error = (self as Any) as? NSError else { - - return .Unknown - } - - guard error.domain == CoreStoreErrorDomain else { - - return .InternalError(NSError: error) - } - - 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) - } - } - - internal var objc: NSError { - - guard let error = self as? CoreStoreError else { - - return ((self as Any) as? NSError) ?? self as NSError - } - - let code: CoreStoreErrorCode - let info: [NSObject: AnyObject] - switch error { - - 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 - ] - } - - return NSError(domain: CoreStoreErrorDomain, code: code.rawValue, userInfo: info) - } -} diff --git a/Sources/Internal/WeakObject.swift b/Sources/Internal/WeakObject.swift index 0b76a45..98233e6 100644 --- a/Sources/Internal/WeakObject.swift +++ b/Sources/Internal/WeakObject.swift @@ -23,8 +23,6 @@ // SOFTWARE. // -import Foundation - // MARK: - WeakObject diff --git a/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift b/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift index 27501e0..27c8d14 100644 --- a/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift +++ b/Sources/ObjectiveC/CSAsynchronousDataTransaction.swift @@ -28,11 +28,189 @@ import Foundation // MARK: - CSAsynchronousDataTransaction +/** + The `CSAsynchronousDataTransaction` serves as the Objective-C bridging type for `AsynchronousDataTransaction`. + */ @objc public final class CSAsynchronousDataTransaction: CSBaseDataTransaction { - internal init(_ swiftObject: AsynchronousDataTransaction) { +// /** +// 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() +// } +// +// /** +// 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) + // } + + + // MARK: CoreStoreBridge + + internal override var swift: AsynchronousDataTransaction { + + return super.swift as! AsynchronousDataTransaction + } + + public required init(_ swiftObject: AsynchronousDataTransaction) { super.init(swiftObject) } + + required public init(_ swiftObject: BaseDataTransaction) { + + fatalError("init has not been implemented") + } +} + + +// MARK: - AsynchronousDataTransaction + +extension AsynchronousDataTransaction { + + // MARK: CoreStoreBridgeable + + internal typealias ObjCType = CSAsynchronousDataTransaction } diff --git a/Sources/ObjectiveC/CSBaseDataTransaction.swift b/Sources/ObjectiveC/CSBaseDataTransaction.swift index 12c546c..75bb642 100644 --- a/Sources/ObjectiveC/CSBaseDataTransaction.swift +++ b/Sources/ObjectiveC/CSBaseDataTransaction.swift @@ -26,24 +26,13 @@ import Foundation -// MARK: - DataStack - -extension BaseDataTransaction { - - var objc: CSBaseDataTransaction { - - return CSBaseDataTransaction(self) - } -} - - // MARK: - CSBaseDataTransaction /** The `CSBaseDataTransaction` serves as the Objective-C bridging type for `BaseDataTransaction`. */ @objc -public class CSBaseDataTransaction: NSObject { +public class CSBaseDataTransaction: NSObject, CoreStoreBridge { // MARK: Object management @@ -59,13 +48,13 @@ public class CSBaseDataTransaction: NSObject { /** Creates a new `NSManagedObject` with the specified entity type. - - parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration + - 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 func create(into into: NSManagedObject.Type) -> NSManagedObject { + public func createInto(into: CSInto) -> NSManagedObject { - return self.swift.create(Into(into)) + return self.swift.create(into.swift) } /** @@ -76,329 +65,209 @@ public class CSBaseDataTransaction: NSObject { */ @objc @warn_unused_result - public func edit(object: NSManagedObject?) -> NSManagedObject? { + public func editObject(object: NSManagedObject?) -> NSManagedObject? { return self.swift.edit(object) } -// /** -// Returns an editable proxy of the object with the specified `NSManagedObjectID`. -// -// - parameter into: an `Into` clause specifying the entity type -// - parameter objectID: the `NSManagedObjectID` for the object to be edited -// - returns: an editable proxy for the specified `NSManagedObject`. -// */ -// @warn_unused_result -// public func edit(into: Into, _ objectID: NSManagedObjectID) -> T? { -// -// CoreStore.assert( -// self.isRunningInAllowedQueue(), -// "Attempted to update an entity of type \(typeName(T)) outside its designated queue." -// ) -// CoreStore.assert( -// into.inferStoreIfPossible -// || (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName, -// "Attempted to update an entity of type \(typeName(T)) but the specified persistent store do not match the `NSManagedObjectID`." -// ) -// return self.fetchExisting(objectID) as? T -// } -// -// /** -// Deletes a specified `NSManagedObject`. -// -// - parameter object: the `NSManagedObject` to be deleted -// */ -// public func delete(object: NSManagedObject?) { -// -// CoreStore.assert( -// self.isRunningInAllowedQueue(), -// "Attempted to delete an entity outside its designated queue." -// ) -// guard let object = object else { -// -// return -// } -// self.context.fetchExisting(object)?.deleteFromContext() -// } -// -// /** -// Deletes the specified `NSManagedObject`s. -// -// - parameter object1: the `NSManagedObject` to be deleted -// - parameter object2: another `NSManagedObject` to be deleted -// - parameter objects: other `NSManagedObject`s to be deleted -// */ -// public func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) { -// -// self.delete(([object1, object2] + objects).flatMap { $0 }) -// } -// -// /** -// Deletes the specified `NSManagedObject`s. -// -// - parameter objects: the `NSManagedObject`s to be deleted -// */ -// public func delete(objects: S) { -// -// CoreStore.assert( -// self.isRunningInAllowedQueue(), -// "Attempted to delete entities outside their designated queue." -// ) -// -// let context = self.context -// objects.forEach { context.fetchExisting($0)?.deleteFromContext() } -// } -// -// /** -// Refreshes all registered objects `NSManagedObject`s in the transaction. -// */ -// public func refreshAllObjectsAsFaults() { -// -// CoreStore.assert( -// self.isRunningInAllowedQueue(), -// "Attempted to refresh entities outside their designated queue." -// ) -// -// self.context.refreshAllObjectsAsFaults() -// } -// -// -// // 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: a `Set` of pending `NSManagedObject`s that were inserted to the transaction. -// */ -// public func insertedObjects() -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access inserted objects from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access inserted objects from an already committed \(typeName(self))." -// ) -// -// return self.context.insertedObjects -// } -// -// /** -// Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called. -// -// - parameter entity: the `NSManagedObject` subclass to filter -// - returns: a `Set` of pending `NSManagedObject`s of the specified type that were inserted to the transaction. -// */ -// public func insertedObjects(entity: T.Type) -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access inserted objects from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access inserted objects from an already committed \(typeName(self))." -// ) -// -// return Set(self.context.insertedObjects.flatMap { $0 as? T }) -// } -// -// /** -// Returns all pending `NSManagedObjectID`s that were inserted to the transaction. This method should not be called after the `commit()` method was called. -// -// - returns: a `Set` of pending `NSManagedObjectID`s that were inserted to the transaction. -// */ -// public func insertedObjectIDs() -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access inserted object IDs from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access inserted objects IDs from an already committed \(typeName(self))." -// ) -// -// return Set(self.context.insertedObjects.map { $0.objectID }) -// } -// -// /** -// Returns all pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called. -// -// - parameter entity: the `NSManagedObject` subclass to filter -// - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction. -// */ -// public func insertedObjectIDs(entity: T.Type) -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access inserted object IDs from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access inserted objects IDs from an already committed \(typeName(self))." -// ) -// -// return Set(self.context.insertedObjects.flatMap { $0 as? T }.map { $0.objectID }) -// } -// -// /** -// Returns all pending `NSManagedObject`s that were updated in the transaction. This method should not be called after the `commit()` method was called. -// -// - returns: a `Set` of pending `NSManagedObject`s that were updated to the transaction. -// */ -// public func updatedObjects() -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access updated objects from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access updated objects from an already committed \(typeName(self))." -// ) -// -// return self.context.updatedObjects -// } -// -// /** -// Returns all pending `NSManagedObject`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called. -// -// - parameter entity: the `NSManagedObject` subclass to filter -// - returns: a `Set` of pending `NSManagedObject`s of the specified type that were updated in the transaction. -// */ -// public func updatedObjects(entity: T.Type) -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access updated objects from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access updated objects from an already committed \(typeName(self))." -// ) -// -// return Set(self.context.updatedObjects.flatMap { $0 as? T }) -// } -// -// /** -// Returns all pending `NSManagedObjectID`s that were updated in the transaction. This method should not be called after the `commit()` method was called. -// -// - returns: a `Set` of pending `NSManagedObjectID`s that were updated in the transaction. -// */ -// public func updatedObjectIDs() -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access updated object IDs from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access updated object IDs from an already committed \(typeName(self))." -// ) -// -// return Set(self.context.updatedObjects.map { $0.objectID }) -// } -// -// /** -// Returns all pending `NSManagedObjectID`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called. -// -// - parameter entity: the `NSManagedObject` subclass to filter -// - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction. -// */ -// public func updatedObjectIDs(entity: T.Type) -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access updated object IDs from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access updated object IDs from an already committed \(typeName(self))." -// ) -// -// return Set(self.context.updatedObjects.flatMap { $0 as? T }.map { $0.objectID }) -// } -// -// /** -// Returns all pending `NSManagedObject`s that were deleted from the transaction. This method should not be called after the `commit()` method was called. -// -// - returns: a `Set` of pending `NSManagedObject`s that were deleted from the transaction. -// */ -// public func deletedObjects() -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access deleted objects from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access deleted objects from an already committed \(typeName(self))." -// ) -// -// return self.context.deletedObjects -// } -// -// /** -// Returns all pending `NSManagedObject`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called. -// -// - parameter entity: the `NSManagedObject` subclass to filter -// - returns: a `Set` of pending `NSManagedObject`s of the specified type that were deleted from the transaction. -// */ -// public func deletedObjects(entity: T.Type) -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access deleted objects from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access deleted objects from an already committed \(typeName(self))." -// ) -// -// return Set(self.context.deletedObjects.flatMap { $0 as? T }) -// } -// -// /** -// Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called. -// -// - parameter entity: the `NSManagedObject` subclass to filter -// - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. -// */ -// public func deletedObjectIDs() -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access deleted object IDs from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access deleted object IDs from an already committed \(typeName(self))." -// ) -// -// return Set(self.context.deletedObjects.map { $0.objectID }) -// } -// -// /** -// Returns all pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called. -// -// - parameter entity: the `NSManagedObject` subclass to filter -// - returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction. -// */ -// public func deletedObjectIDs(entity: T.Type) -> Set { -// -// CoreStore.assert( -// self.transactionQueue.isCurrentExecutionContext(), -// "Attempted to access deleted object IDs from a \(typeName(self)) outside its designated queue." -// ) -// CoreStore.assert( -// !self.isCommitted, -// "Attempted to access deleted object IDs from an already committed \(typeName(self))." -// ) -// -// return Set(self.context.deletedObjects.flatMap { $0 as? T }.map { $0.objectID }) -// } + /** + Returns an editable proxy of the object with the specified `NSManagedObjectID`. + + - 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 func editInto(into: CSInto, objectID: NSManagedObjectID) -> NSManagedObject? { + + return self.swift.edit(into.swift, objectID) + } + + /** + Deletes a specified `NSManagedObject`. + + - parameter object: the `NSManagedObject` to be deleted + */ + @objc + public func deleteObject(object: NSManagedObject?) { + + self.swift.delete(object) + } + + /** + Deletes the specified `NSManagedObject`s. + + - parameter objects: the `NSManagedObject`s to be deleted + */ + @objc + public func deleteObjects(objects: [NSManagedObject]) { + + self.swift.delete(objects) + } + + /** + Refreshes all registered objects `NSManagedObject`s in the transaction. + */ + @objc + public func refreshAllObjectsAsFaults() { + + self.swift.refreshAllObjectsAsFaults() + } + + + // MARK: Inspecting Pending Objects + + /** + Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `commit()` method was called. + + - returns: an `NSSet` of pending `NSManagedObject`s that were inserted to the transaction. + */ + @objc + @warn_unused_result + public func insertedObjects() -> Set { + + return self.swift.insertedObjects() + } + + /** + Returns all pending `NSManagedObject`s of the specified type that were inserted to the transaction. This method should not be called after the `commit()` method was called. + + - parameter entity: the `NSManagedObject` subclass to filter + - returns: 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 { + + return self.swift.insertedObjects(entity) + } + + /** + 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. + */ + @objc + @warn_unused_result + public func insertedObjectIDs() -> Set { + + return self.swift.insertedObjectIDs() + } + + /** + 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. + */ + @objc + @warn_unused_result + public func insertedObjectIDsOfType(entity: NSManagedObject.Type) -> Set { + + return self.swift.insertedObjectIDs(entity) + } + + /** + Returns all pending `NSManagedObject`s that were updated in the transaction. This method should not be called after the `commit()` method was called. + + - returns: an `NSSet` of pending `NSManagedObject`s that were updated to the transaction. + */ + @objc + @warn_unused_result + public func updatedObjects() -> Set { + + return self.swift.updatedObjects() + } + + /** + Returns all pending `NSManagedObject`s of the specified type that were updated in the transaction. This method should not be called after the `commit()` method was called. + + - parameter entity: the `NSManagedObject` subclass to filter + - returns: 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 { + + return self.swift.updatedObjects(entity) + } + + /** + 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. + */ + @objc + @warn_unused_result + public func updatedObjectIDs() -> Set { + + return self.swift.updatedObjectIDs() + } + + /** + 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. + */ + @objc + @warn_unused_result + public func updatedObjectIDsOfType(entity: NSManagedObject.Type) -> Set { + + return self.swift.updatedObjectIDs(entity) + } + + /** + Returns all pending `NSManagedObject`s that were deleted from the transaction. This method should not be called after the `commit()` method was called. + + - returns: an `NSSet` of pending `NSManagedObject`s that were deleted from the transaction. + */ + @objc + @warn_unused_result + public func deletedObjects() -> Set { + + return self.swift.deletedObjects() + } + + /** + Returns all pending `NSManagedObject`s of the specified type that were deleted from the transaction. This method should not be called after the `commit()` method was called. + + - parameter entity: the `NSManagedObject` subclass to filter + - returns: 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 { + + return self.swift.deletedObjects(entity) + } + + /** + 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. + */ + @objc + @warn_unused_result + public func deletedObjectIDs() -> Set { + + return self.swift.deletedObjectIDs() + } + + /** + 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. + */ + @objc + @warn_unused_result + public func deletedObjectIDsOfType(entity: NSManagedObject.Type) -> Set { + + return self.swift.deletedObjectIDs(entity) + } // MARK: NSObject @@ -420,11 +289,26 @@ public class CSBaseDataTransaction: NSObject { // MARK: CoreStoreBridge - internal let swift: BaseDataTransaction - - internal init(_ swiftObject: BaseDataTransaction) { + public required init(_ swiftObject: BaseDataTransaction) { - self.swift = swiftObject + self.swiftObject = swiftObject super.init() } + + internal var swift: BaseDataTransaction { + + return self.swiftObject + } + + private let swiftObject: BaseDataTransaction +} + + +// MARK: - BaseDataTransaction + +extension BaseDataTransaction: CoreStoreBridgeable { + + // MARK: CoreStoreBridgeable + + internal typealias ObjCType = CSBaseDataTransaction } diff --git a/Sources/ObjectiveC/CSCoreStore+Setup.swift b/Sources/ObjectiveC/CSCoreStore+Setup.swift index c59c144..d1b654a 100644 --- a/Sources/ObjectiveC/CSCoreStore+Setup.swift +++ b/Sources/ObjectiveC/CSCoreStore+Setup.swift @@ -28,6 +28,17 @@ public extension CSCoreStore { return CoreStore.defaultStack.entityTypesByName } + /** + Returns the entity class for the given entity name from the `defaultStack`'s model. + - parameter name: the entity name + - returns: the `NSManagedObject` class for the given entity name, or `nil` if not found + */ + @objc + public static func entityClassWithName(name: String) -> NSManagedObject.Type? { + + return CoreStore.defaultStack.entityTypesByName[name] + } + /** Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model. */ diff --git a/Sources/ObjectiveC/CSDataStack.swift b/Sources/ObjectiveC/CSDataStack.swift index a4e281d..4bb1968 100644 --- a/Sources/ObjectiveC/CSDataStack.swift +++ b/Sources/ObjectiveC/CSDataStack.swift @@ -27,16 +27,6 @@ import Foundation import CoreData -// MARK: - DataStack - -extension DataStack: CoreStoreBridgeable { - - // MARK: CoreStoreBridgeable - - public typealias ObjCType = CSDataStack -} - - // MARK: - CSDataStack /** @@ -144,6 +134,17 @@ public final class CSDataStack: NSObject, CoreStoreBridge { return self.swift.entityTypesByName } + /** + Returns the entity class for the given entity name from the stack's's model. + - parameter name: the entity name + - returns: the `NSManagedObject` class for the given entity name, or `nil` if not found + */ + @objc + public func entityClassWithName(name: String) -> NSManagedObject.Type? { + + return self.swift.entityTypesByName[name] + } + /** Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from stack's model. */ @@ -249,10 +250,20 @@ public final class CSDataStack: NSObject, CoreStoreBridge { // MARK: CoreStoreBridge - public let swift: DataStack + internal let swift: DataStack - public required init(_ swiftObject: DataStack) { + internal init(_ swiftObject: DataStack) { self.swift = swiftObject } } + + +// MARK: - DataStack + +extension DataStack: CoreStoreBridgeable { + + // MARK: CoreStoreBridgeable + + internal typealias ObjCType = CSDataStack +} diff --git a/Sources/ObjectiveC/CSError.swift b/Sources/ObjectiveC/CSError.swift index 758c361..8e5aa3e 100644 --- a/Sources/ObjectiveC/CSError.swift +++ b/Sources/ObjectiveC/CSError.swift @@ -80,3 +80,114 @@ public enum CSErrorCode: Int { */ case InternalError } + + +// MARK: Internal + +internal extension ErrorType { + + internal var swift: CoreStoreError { + + if case let error as CoreStoreError = self { + + return error + } + + guard let error = (self as Any) as? NSError else { + + return .Unknown + } + + guard error.domain == CoreStoreErrorDomain else { + + return .InternalError(NSError: error) + } + + 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) + } + } + + internal var objc: NSError { + + guard let error = self as? CoreStoreError else { + + return ((self as Any) as? NSError) ?? self as NSError + } + + let code: CoreStoreErrorCode + let info: [NSObject: AnyObject] + switch error { + + 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 + ] + } + + return NSError(domain: CoreStoreErrorDomain, code: code.rawValue, userInfo: info) + } +} diff --git a/Sources/ObjectiveC/CSInMemoryStore.swift b/Sources/ObjectiveC/CSInMemoryStore.swift index 71dc403..e66bd0c 100644 --- a/Sources/ObjectiveC/CSInMemoryStore.swift +++ b/Sources/ObjectiveC/CSInMemoryStore.swift @@ -27,16 +27,6 @@ import Foundation import CoreData -// MARK: - InMemoryStore - -extension InMemoryStore: CoreStoreBridgeable { - - // MARK: CoreStoreBridgeable - - public typealias ObjCType = CSInMemoryStore -} - - // MARK: - CSInMemoryStore /** @@ -112,10 +102,20 @@ public final class CSInMemoryStore: NSObject, CSStorageInterface, CoreStoreBridg // MARK: CoreStoreBridge - public let swift: InMemoryStore + internal let swift: InMemoryStore public required init(_ swiftObject: InMemoryStore) { self.swift = swiftObject } } + + +// MARK: - InMemoryStore + +extension InMemoryStore: CoreStoreBridgeable { + + // MARK: CoreStoreBridgeable + + internal typealias ObjCType = CSInMemoryStore +} diff --git a/Sources/ObjectiveC/CSInto.swift b/Sources/ObjectiveC/CSInto.swift new file mode 100644 index 0000000..7c4a1fa --- /dev/null +++ b/Sources/ObjectiveC/CSInto.swift @@ -0,0 +1,95 @@ +// +// CSInto.swift +// CoreStore +// +// Created by John Estropia on 2016/03/24. +// Copyright © 2016年 John Rommel Estropia. All rights reserved. +// + +import UIKit + + +// MARK: - CSInto + +/** + The `CSInto` serves as the Objective-C bridging type for `Into`. + */ +@objc +public final class CSInto: NSObject, CoreStoreBridge { + + /** + Initializes a `CSInto` clause with the specified entity class. + Sample Usage: + ``` + MyPersonEntity *person = [transaction create:[CSInto entityClass:[MyPersonEntity class]]]; + ``` + - parameter entityClass: the `NSManagedObject` class type to be created + - returns: a new `CSInto` with the specified entity class + */ + @objc + public static func entityClass(entityClass: AnyClass) -> CSInto { + + return self.init(Into(entityClass)) + } + + /** + Initializes an `CSInto` clause with the specified configuration. + Sample Usage: + ``` + MyPersonEntity *person = [transaction create:[CSInto entityClass:[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. + - returns: a new `CSInto` with the specified configuration + */ + @objc + public static func entityClass(entityClass: AnyClass, configuration: String?) -> CSInto { + + return self.init(Into(entityClass, configuration)) + } + + + // MARK: NSObject + + public override var hash: Int { + + return self.swift.hashValue + } + + public override func isEqual(object: AnyObject?) -> Bool { + + guard let object = object as? CSInto else { + + return false + } + return self.swift == object.swift + } + + + // MARK: CoreStoreBridge + + internal let swift: Into + + public required init(_ swiftObject: Into) { + + self.swift = Into( + entityClass: swiftObject.entityClass, + configuration: swiftObject.configuration, + inferStoreIfPossible: swiftObject.inferStoreIfPossible + ) + super.init() + } +} + + +// MARK: - Into + +extension Into: CoreStoreBridgeable { + + // MARK: CoreStoreBridgeable + + internal var objc: CSInto { + + return CSInto(self) + } +} diff --git a/Sources/ObjectiveC/CSSQliteStore.swift b/Sources/ObjectiveC/CSSQliteStore.swift index 4584a66..d17ba1b 100644 --- a/Sources/ObjectiveC/CSSQliteStore.swift +++ b/Sources/ObjectiveC/CSSQliteStore.swift @@ -27,16 +27,6 @@ import Foundation import CoreData -// MARK: - SQLiteStore - -extension SQLiteStore: CoreStoreBridgeable { - - // MARK: CoreStoreBridgeable - - public typealias ObjCType = CSSQLiteStore -} - - // MARK: - CSSQLiteStore /** @@ -189,10 +179,20 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreBridge { // MARK: CoreStoreBridge - public let swift: SQLiteStore + internal let swift: SQLiteStore public required init(_ swiftObject: SQLiteStore) { self.swift = swiftObject } } + + +// MARK: - SQLiteStore + +extension SQLiteStore: CoreStoreBridgeable { + + // MARK: CoreStoreBridgeable + + internal typealias ObjCType = CSSQLiteStore +} diff --git a/Sources/ObjectiveC/CoreStoreBridge.swift b/Sources/ObjectiveC/CoreStoreBridge.swift index 15dfb99..96a55d1 100644 --- a/Sources/ObjectiveC/CoreStoreBridge.swift +++ b/Sources/ObjectiveC/CoreStoreBridge.swift @@ -28,7 +28,7 @@ import Foundation // MARK: - CoreStoreBridge -public protocol CoreStoreBridge: class, AnyObject { +internal protocol CoreStoreBridge: class, AnyObject { associatedtype SwiftType @@ -40,42 +40,18 @@ public protocol CoreStoreBridge: class, AnyObject { // MARK: - CoreStoreBridgeable -public protocol CoreStoreBridgeable: _ObjectiveCBridgeable { +internal protocol CoreStoreBridgeable { associatedtype ObjCType: CoreStoreBridge + + var objc: ObjCType { get } } -public extension CoreStoreBridgeable where Self == ObjCType.SwiftType { - - static func _isBridgedToObjectiveC() -> Bool { - - return true - } - - static func _getObjectiveCType() -> Any.Type { - - return ObjCType.self - } - - func _bridgeToObjectiveC() -> ObjCType { - - return ObjCType(self) - } - - static func _forceBridgeFromObjectiveC(source: ObjCType, inout result: ObjCType.SwiftType?) { - - result = source.swift - } - - static func _conditionallyBridgeFromObjectiveC(source: ObjCType, inout result: ObjCType.SwiftType?) -> Bool { - - result = source.swift - return true - } +internal extension CoreStoreBridgeable where Self == ObjCType.SwiftType { var objc: ObjCType { - return self._bridgeToObjectiveC() + return ObjCType(self) } } diff --git a/Sources/Saving and Processing/BaseDataTransaction.swift b/Sources/Saving and Processing/BaseDataTransaction.swift index 714bd83..0588e01 100644 --- a/Sources/Saving and Processing/BaseDataTransaction.swift +++ b/Sources/Saving and Processing/BaseDataTransaction.swift @@ -208,7 +208,8 @@ public /*abstract*/ class BaseDataTransaction { Returns all pending `NSManagedObject`s that were inserted to the transaction. This method should not be called after the `commit()` method was called. - returns: a `Set` of pending `NSManagedObject`s that were inserted to the transaction. - */ + */ + @warn_unused_result public func insertedObjects() -> Set { CoreStore.assert( @@ -229,6 +230,7 @@ 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 { CoreStore.assert( @@ -248,6 +250,7 @@ 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( @@ -268,6 +271,7 @@ 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 { CoreStore.assert( @@ -279,7 +283,7 @@ public /*abstract*/ class BaseDataTransaction { "Attempted to access inserted objects IDs from an already committed \(typeName(self))." ) - return Set(self.context.insertedObjects.flatMap { $0 as? T }.map { $0.objectID }) + return Set(self.context.insertedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID }) } /** @@ -287,6 +291,7 @@ 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( @@ -307,6 +312,7 @@ 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 { CoreStore.assert( @@ -318,7 +324,7 @@ public /*abstract*/ class BaseDataTransaction { "Attempted to access updated objects from an already committed \(typeName(self))." ) - return Set(self.context.updatedObjects.flatMap { $0 as? T }) + return Set(self.context.updatedObjects.filter { $0.isKindOfClass(entity) }.map { $0 as! T }) } /** @@ -326,6 +332,7 @@ 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( @@ -346,6 +353,7 @@ 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 { CoreStore.assert( @@ -357,7 +365,7 @@ public /*abstract*/ class BaseDataTransaction { "Attempted to access updated object IDs from an already committed \(typeName(self))." ) - return Set(self.context.updatedObjects.flatMap { $0 as? T }.map { $0.objectID }) + return Set(self.context.updatedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID }) } /** @@ -365,6 +373,7 @@ 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( @@ -385,6 +394,7 @@ 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 { CoreStore.assert( @@ -396,7 +406,7 @@ public /*abstract*/ class BaseDataTransaction { "Attempted to access deleted objects from an already committed \(typeName(self))." ) - return Set(self.context.deletedObjects.flatMap { $0 as? T }) + return Set(self.context.deletedObjects.filter { $0.isKindOfClass(entity) }.map { $0 as! T }) } /** @@ -405,6 +415,7 @@ 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( @@ -425,6 +436,7 @@ 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 { CoreStore.assert( @@ -436,7 +448,7 @@ public /*abstract*/ class BaseDataTransaction { "Attempted to access deleted object IDs from an already committed \(typeName(self))." ) - return Set(self.context.deletedObjects.flatMap { $0 as? T }.map { $0.objectID }) + return Set(self.context.deletedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID }) } diff --git a/Sources/Saving and Processing/Into.swift b/Sources/Saving and Processing/Into.swift index 20159fb..1f1a623 100644 --- a/Sources/Saving and Processing/Into.swift +++ b/Sources/Saving and Processing/Into.swift @@ -39,7 +39,7 @@ import CoreData let person = transaction.create(Into("Configuration1")) ``` */ -public struct Into { +public struct Into: Hashable { /** Initializes an `Into` clause. @@ -50,9 +50,7 @@ public struct Into { */ public init(){ - self.configuration = nil - self.inferStoreIfPossible = true - self.entityClass = T.self + self.init(entityClass: T.self, configuration: nil, inferStoreIfPossible: true) } /** @@ -65,9 +63,7 @@ public struct Into { */ public init(_ entity: T.Type) { - self.configuration = nil - self.inferStoreIfPossible = true - self.entityClass = entity + self.init(entityClass: entity, configuration: nil, inferStoreIfPossible: true) } /** @@ -80,9 +76,7 @@ public struct Into { */ public init(_ entityClass: AnyClass) { - self.configuration = nil - self.inferStoreIfPossible = true - self.entityClass = entityClass + self.init(entityClass: entityClass, configuration: nil, inferStoreIfPossible: true) } /** @@ -95,9 +89,7 @@ public struct Into { */ public init(_ configuration: String?) { - self.configuration = configuration - self.inferStoreIfPossible = false - self.entityClass = T.self + self.init(entityClass: T.self, configuration: configuration, inferStoreIfPossible: false) } /** @@ -111,9 +103,7 @@ public struct Into { */ public init(_ entity: T.Type, _ configuration: String?) { - self.configuration = configuration - self.inferStoreIfPossible = false - self.entityClass = entity + self.init(entityClass: entity, configuration: configuration, inferStoreIfPossible: false) } /** @@ -127,9 +117,17 @@ public struct Into { */ public init(_ entityClass: AnyClass, _ configuration: String?) { - self.configuration = configuration - self.inferStoreIfPossible = false - self.entityClass = entityClass + self.init(entityClass: entityClass, configuration: configuration, inferStoreIfPossible: false) + } + + + // MARK: Hashable + + public var hashValue: Int { + + return ObjectIdentifier(self.entityClass).hashValue + ^ (self.configuration?.hashValue ?? 0) + ^ self.inferStoreIfPossible.hashValue } @@ -143,4 +141,48 @@ public struct Into { internal let entityClass: AnyClass internal let configuration: String? internal let inferStoreIfPossible: Bool + + internal init(entityClass: AnyClass, configuration: String?, inferStoreIfPossible: Bool) { + + self.entityClass = entityClass + 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 +} + + +// 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 }