Merge branch 'swift3_develop' into develop

# Conflicts:
#	.travis.yml
#	CoreStore.podspec
#	CoreStore.xcodeproj/project.pbxproj
#	Sources/Info.plist
This commit is contained in:
John Estropia
2017-01-06 16:03:28 +09:00
162 changed files with 6807 additions and 6464 deletions

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - AsynchronousDataTransaction
@@ -42,10 +39,10 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block.
*/
public func commit(completion: (result: SaveResult) -> Void = { _ in }) {
public func commit(_ completion: @escaping (_ result: SaveResult) -> Void = { _ in }) {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -54,12 +51,12 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
)
self.isCommitted = true
let group = GCDGroup()
let group = DispatchGroup()
group.enter()
self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
self.result = result
completion(result: result)
completion(result)
group.leave()
}
group.wait()
@@ -71,10 +68,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
*/
public func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
@discardableResult
public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to begin a child transaction from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -97,11 +95,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
- returns: a new `NSManagedObject` instance of the specified entity type.
*/
public override func create<T: NSManagedObject>(into: Into<T>) -> T {
public override func create<T: NSManagedObject>(_ into: Into<T>) -> T {
CoreStore.assert(
!self.isCommitted,
"Attempted to create an entity of type \(cs_typeName(T)) from an already committed \(cs_typeName(self))."
"Attempted to create an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
)
return super.create(into)
@@ -113,8 +111,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public override func edit<T: NSManagedObject>(object: T?) -> T? {
public override func edit<T: NSManagedObject>(_ object: T?) -> T? {
CoreStore.assert(
!self.isCommitted,
@@ -131,12 +128,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public override func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
public override func edit<T: NSManagedObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert(
!self.isCommitted,
"Attempted to update an entity of type \(cs_typeName(T)) from an already committed \(cs_typeName(self))."
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
)
return super.edit(into, objectID)
@@ -147,7 +143,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be deleted
*/
public override func delete(object: NSManagedObject?) {
public override func delete(_ object: NSManagedObject?) {
CoreStore.assert(
!self.isCommitted,
@@ -164,7 +160,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter object2: another `NSManagedObject` type to be deleted
- parameter objects: other `NSManagedObject`s type to be deleted
*/
public override func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
public override func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
CoreStore.assert(
!self.isCommitted,
@@ -179,7 +175,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
- parameter objects: the `NSManagedObject`s type to be deleted
*/
public override func delete<S: SequenceType where S.Generator.Element: NSManagedObject>(objects: S) {
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: NSManagedObject {
CoreStore.assert(
!self.isCommitted,
@@ -192,7 +188,7 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
// MARK: Internal
internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, closure: (transaction: AsynchronousDataTransaction) -> Void) {
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
self.closure = closure
@@ -203,11 +199,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
self.transactionQueue.async {
self.closure(transaction: self)
self.closure(self)
if !self.isCommitted && self.hasChanges {
CoreStore.log(
.Warning,
.warning,
message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
)
}
@@ -218,12 +214,12 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
self.transactionQueue.sync {
self.closure(transaction: self)
self.closure(self)
if !self.isCommitted && self.hasChanges {
CoreStore.log(
.Warning,
.warning,
message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
)
}
@@ -234,23 +230,5 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
// MARK: Private
private let closure: (transaction: AsynchronousDataTransaction) -> Void
// MARK: Deprecated
@available(*, deprecated=1.3.4, obsoleted=2.0.0, message="Resetting the context is inherently unsafe. This method will be removed in the near future. Use `beginUnsafe()` to create transactions with `undo` support.")
public func rollback() {
CoreStore.assert(
!self.isCommitted,
"Attempted to rollback an already committed \(cs_typeName(self))."
)
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
"Attempted to rollback a \(cs_typeName(self)) outside its designated queue."
)
self.context.reset()
}
private let closure: (_ transaction: AsynchronousDataTransaction) -> Void
}

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - BaseDataTransaction
@@ -53,15 +50,15 @@ public /*abstract*/ class BaseDataTransaction {
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
- returns: a new `NSManagedObject` instance of the specified entity type.
*/
public func create<T: NSManagedObject>(into: Into<T>) -> T {
public func create<T: NSManagedObject>(_ into: Into<T>) -> T {
let entityClass = (into.entityClass as! T.Type)
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to create an entity of type \(cs_typeName(T)) outside its designated queue."
"Attempted to create an entity of type \(cs_typeName(entityClass)) outside its designated queue."
)
let context = self.context
let entityClass = (into.entityClass as! NSManagedObject.Type)
if into.inferStoreIfPossible {
switch context.parentStack!.persistentStoreForEntityClass(
@@ -71,8 +68,8 @@ public /*abstract*/ class BaseDataTransaction {
) {
case (let persistentStore?, _):
let object = entityClass.createInContext(context) as! T
context.assignObject(object, toPersistentStore: persistentStore)
let object = entityClass.createInContext(context)
context.assign(object, to: persistentStore)
return object
case (nil, true):
@@ -87,13 +84,13 @@ public /*abstract*/ class BaseDataTransaction {
switch context.parentStack!.persistentStoreForEntityClass(
entityClass,
configuration: into.configuration
?? into.dynamicType.defaultConfigurationName,
?? type(of: into).defaultConfigurationName,
inferStoreIfPossible: false
) {
case (let persistentStore?, _):
let object = entityClass.createInContext(context) as! T
context.assignObject(object, toPersistentStore: persistentStore)
let object = entityClass.createInContext(context)
context.assign(object, to: persistentStore)
return object
case (nil, true):
@@ -118,8 +115,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public func edit<T: NSManagedObject>(object: T?) -> T? {
public func edit<T: NSManagedObject>(_ object: T?) -> T? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -139,17 +135,16 @@ public /*abstract*/ class BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
public func edit<T: NSManagedObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert(
self.isRunningInAllowedQueue(),
"Attempted to update an entity of type \(cs_typeName(T)) outside its designated queue."
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) outside its designated queue."
)
CoreStore.assert(
into.inferStoreIfPossible
|| (into.configuration ?? Into.defaultConfigurationName) == objectID.persistentStore?.configurationName,
"Attempted to update an entity of type \(cs_typeName(T)) but the specified persistent store do not match the `NSManagedObjectID`."
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) but the specified persistent store do not match the `NSManagedObjectID`."
)
return self.fetchExisting(objectID) as? T
}
@@ -159,7 +154,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object: the `NSManagedObject` to be deleted
*/
public func delete(object: NSManagedObject?) {
public func delete(_ object: NSManagedObject?) {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -179,7 +174,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter object2: another `NSManagedObject` to be deleted
- parameter objects: other `NSManagedObject`s to be deleted
*/
public func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
public func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
self.delete(([object1, object2] + objects).flatMap { $0 })
}
@@ -189,7 +184,7 @@ public /*abstract*/ class BaseDataTransaction {
- parameter objects: the `NSManagedObject`s to be deleted
*/
public func delete<S: SequenceType where S.Generator.Element: NSManagedObject>(objects: S) {
public func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: NSManagedObject {
CoreStore.assert(
self.isRunningInAllowedQueue(),
@@ -221,11 +216,10 @@ public /*abstract*/ class BaseDataTransaction {
- returns: a `Set` of pending `NSManagedObject`s that were inserted to the transaction.
*/
@warn_unused_result
public func insertedObjects() -> Set<NSManagedObject> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -242,11 +236,10 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were inserted to the transaction.
*/
@warn_unused_result
public func insertedObjects<T: NSManagedObject>(entity: T.Type) -> Set<T> {
public func insertedObjects<T: NSManagedObject>(_ entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -262,11 +255,10 @@ public /*abstract*/ class BaseDataTransaction {
- returns: a `Set` of pending `NSManagedObjectID`s that were inserted to the transaction.
*/
@warn_unused_result
public func insertedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -283,11 +275,10 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were inserted to the transaction.
*/
@warn_unused_result
public func insertedObjectIDs<T: NSManagedObject>(entity: T.Type) -> Set<NSManagedObjectID> {
public func insertedObjectIDs<T: NSManagedObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access inserted object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -295,7 +286,7 @@ public /*abstract*/ class BaseDataTransaction {
"Attempted to access inserted objects IDs from an already committed \(cs_typeName(self))."
)
return Set(self.context.insertedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
return Set(self.context.insertedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
}
/**
@@ -303,11 +294,10 @@ public /*abstract*/ class BaseDataTransaction {
- returns: a `Set` of pending `NSManagedObject`s that were updated to the transaction.
*/
@warn_unused_result
public func updatedObjects() -> Set<NSManagedObject> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -324,11 +314,10 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were updated in the transaction.
*/
@warn_unused_result
public func updatedObjects<T: NSManagedObject>(entity: T.Type) -> Set<T> {
public func updatedObjects<T: NSManagedObject>(_ entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -336,7 +325,7 @@ public /*abstract*/ class BaseDataTransaction {
"Attempted to access updated objects from an already committed \(cs_typeName(self))."
)
return Set(self.context.updatedObjects.filter { $0.isKindOfClass(entity) }.map { $0 as! T })
return Set(self.context.updatedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
}
/**
@@ -344,11 +333,10 @@ public /*abstract*/ class BaseDataTransaction {
- returns: a `Set` of pending `NSManagedObjectID`s that were updated in the transaction.
*/
@warn_unused_result
public func updatedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -365,11 +353,10 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were updated in the transaction.
*/
@warn_unused_result
public func updatedObjectIDs<T: NSManagedObject>(entity: T.Type) -> Set<NSManagedObjectID> {
public func updatedObjectIDs<T: NSManagedObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access updated object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -377,7 +364,7 @@ public /*abstract*/ class BaseDataTransaction {
"Attempted to access updated object IDs from an already committed \(cs_typeName(self))."
)
return Set(self.context.updatedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
return Set(self.context.updatedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
}
/**
@@ -385,11 +372,10 @@ public /*abstract*/ class BaseDataTransaction {
- returns: a `Set` of pending `NSManagedObject`s that were deleted from the transaction.
*/
@warn_unused_result
public func deletedObjects() -> Set<NSManagedObject> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -406,11 +392,10 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObject`s of the specified type that were deleted from the transaction.
*/
@warn_unused_result
public func deletedObjects<T: NSManagedObject>(entity: T.Type) -> Set<T> {
public func deletedObjects<T: NSManagedObject>(_ entity: T.Type) -> Set<T> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted objects from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -418,7 +403,7 @@ public /*abstract*/ class BaseDataTransaction {
"Attempted to access deleted objects from an already committed \(cs_typeName(self))."
)
return Set(self.context.deletedObjects.filter { $0.isKindOfClass(entity) }.map { $0 as! T })
return Set(self.context.deletedObjects.filter { $0.isKind(of: entity) }.map { $0 as! T })
}
/**
@@ -427,11 +412,10 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/
@warn_unused_result
public func deletedObjectIDs() -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -448,11 +432,10 @@ public /*abstract*/ class BaseDataTransaction {
- parameter entity: the `NSManagedObject` subclass to filter
- returns: a `Set` of pending `NSManagedObjectID`s of the specified type that were deleted from the transaction.
*/
@warn_unused_result
public func deletedObjectIDs<T: NSManagedObject>(entity: T.Type) -> Set<NSManagedObjectID> {
public func deletedObjectIDs<T: NSManagedObject>(_ entity: T.Type) -> Set<NSManagedObjectID> {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to access deleted object IDs from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -460,28 +443,26 @@ public /*abstract*/ class BaseDataTransaction {
"Attempted to access deleted object IDs from an already committed \(cs_typeName(self))."
)
return Set(self.context.deletedObjects.filter { $0.isKindOfClass(entity) }.map { $0.objectID })
return Set(self.context.deletedObjects.filter { $0.isKind(of: entity) }.map { $0.objectID })
}
// MARK: Internal
internal let context: NSManagedObjectContext
internal let transactionQueue: GCDQueue
internal let childTransactionQueue: GCDQueue = .createSerial("com.corestore.datastack.childtransactionqueue")
internal let transactionQueue: DispatchQueue
internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childtransactionqueue")
internal let supportsUndo: Bool
internal let bypassesQueueing: Bool
internal var isCommitted = false
internal var result: SaveResult?
internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool, bypassesQueueing: Bool) {
let context = mainContext.temporaryContextInTransactionWithConcurrencyType(
queue == .Main
? .MainQueueConcurrencyType
: .PrivateQueueConcurrencyType
queue == .main
? .mainQueueConcurrencyType
: .privateQueueConcurrencyType
)
self.transactionQueue = queue
self.context = context
@@ -489,18 +470,19 @@ public /*abstract*/ class BaseDataTransaction {
self.bypassesQueueing = bypassesQueueing
context.parentTransaction = self
context.isTransactionContext = true
if !supportsUndo {
context.undoManager = nil
}
else if context.undoManager == nil {
context.undoManager = NSUndoManager()
context.undoManager = UndoManager()
}
}
internal func isRunningInAllowedQueue() -> Bool {
return self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext()
return self.bypassesQueueing || self.transactionQueue.cs_isCurrentExecutionContext()
}
}

View File

@@ -35,7 +35,7 @@ public extension CoreStore {
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
*/
public static func beginAsynchronous(closure: (transaction: AsynchronousDataTransaction) -> Void) {
public static func beginAsynchronous(_ closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
self.defaultStack.beginAsynchronous(closure)
}
@@ -46,7 +46,8 @@ public extension CoreStore {
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
*/
public static func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
@discardableResult
public static func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
return self.defaultStack.beginSynchronous(closure)
}
@@ -57,8 +58,7 @@ public extension CoreStore {
- prameter supportsUndo: `undo()`, `redo()`, and `rollback()` methods are only available when this parameter is `true`, otherwise those method will raise an exception. Defaults to `false`. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited.
- returns: a `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
@warn_unused_result
public static func beginUnsafe(supportsUndo supportsUndo: Bool = false) -> UnsafeDataTransaction {
public static func beginUnsafe(supportsUndo: Bool = false) -> UnsafeDataTransaction {
return self.defaultStack.beginUnsafe(supportsUndo: supportsUndo)
}
@@ -70,14 +70,4 @@ public extension CoreStore {
self.defaultStack.refreshAndMergeAllObjects()
}
// MARK: Deprecated
@available(*, deprecated=1.3.1, obsoleted=2.0.0, renamed="beginUnsafe")
@warn_unused_result
public static func beginDetached() -> UnsafeDataTransaction {
return self.beginUnsafe()
}
}

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - DataStack
@@ -39,7 +36,7 @@ public extension DataStack {
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
*/
public func beginAsynchronous(closure: (transaction: AsynchronousDataTransaction) -> Void) {
public func beginAsynchronous(_ closure: @escaping (_ transaction: AsynchronousDataTransaction) -> Void) {
AsynchronousDataTransaction(
mainContext: self.rootSavingContext,
@@ -53,7 +50,8 @@ public extension DataStack {
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
*/
public func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
@discardableResult
public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
return SynchronousDataTransaction(
mainContext: self.rootSavingContext,
@@ -67,15 +65,11 @@ public extension DataStack {
- prameter supportsUndo: `undo()`, `redo()`, and `rollback()` methods are only available when this parameter is `true`, otherwise those method will raise an exception. Defaults to `false`. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited.
- returns: a `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
@warn_unused_result
public func beginUnsafe(supportsUndo supportsUndo: Bool = false) -> UnsafeDataTransaction {
public func beginUnsafe(supportsUndo: Bool = false) -> UnsafeDataTransaction {
return UnsafeDataTransaction(
mainContext: self.rootSavingContext,
queue: .createSerial(
"com.coreStore.dataStack.unsafeTransactionQueue",
targetQueue: .UserInitiated
),
queue: DispatchQueue.serial("com.coreStore.dataStack.unsafeTransactionQueue", qos: .userInitiated),
supportsUndo: supportsUndo
)
}
@@ -86,20 +80,10 @@ public extension DataStack {
public func refreshAndMergeAllObjects() {
CoreStore.assert(
NSThread.isMainThread(),
Thread.isMainThread,
"Attempted to refresh entities outside their designated queue."
)
self.mainContext.refreshAndMergeAllObjects()
}
// MARK: Deprecated
@available(*, deprecated=1.3.1, obsoleted=2.0.0, renamed="beginUnsafe")
@warn_unused_result
public func beginDetached() -> UnsafeDataTransaction {
return self.beginUnsafe()
}
}

View File

@@ -32,7 +32,7 @@ import CoreData
/**
An `Into` clause contains the destination entity and destination persistent store for a `create(...)` method. A common usage is to just indicate the entity:
```
let person = transaction.create(Into(MyPersonEntity))
let person = transaction.create(Into<MyPersonEntity>())
```
For cases where multiple `NSPersistentStore`s contain the same entity, the destination configuration's name needs to be specified as well:
```
@@ -66,9 +66,8 @@ public struct Into<T: NSManagedObject>: Hashable {
/**
Initializes an `Into` clause with the specified entity type.
```
let person = transaction.create(Into(MyPersonEntity))
let person = transaction.create(Into(MyPersonEntity.self))
```
- parameter entity: the `NSManagedObject` type to be created
*/
public init(_ entity: T.Type) {
@@ -79,16 +78,15 @@ public struct Into<T: NSManagedObject>: Hashable {
/**
Initializes an `Into` clause with the specified entity class.
```
let person = transaction.create(Into(MyPersonEntity))
let person = transaction.create(Into(MyPersonEntity.self))
```
- parameter entityClass: the `NSManagedObject` class type to be created
*/
public init(_ entityClass: AnyClass) {
CoreStore.assert(
entityClass is T.Type,
"Attempted to create generic type \(cs_typeName(Into<T>)) with entity class \(cs_typeName(entityClass))"
"Attempted to create generic type \(cs_typeName(Into<T>.self)) with entity class \(cs_typeName(entityClass))"
)
self.init(entityClass: entityClass, configuration: nil, inferStoreIfPossible: true)
}
@@ -98,7 +96,6 @@ public struct Into<T: NSManagedObject>: Hashable {
```
let person = transaction.create(Into<MyPersonEntity>("Configuration1"))
```
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
*/
public init(_ configuration: String?) {
@@ -111,7 +108,6 @@ public struct Into<T: NSManagedObject>: Hashable {
```
let person = transaction.create(Into(MyPersonEntity.self, "Configuration1"))
```
- parameter entity: the `NSManagedObject` type to be created
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
*/
@@ -125,7 +121,6 @@ public struct Into<T: NSManagedObject>: Hashable {
```
let person = transaction.create(Into(MyPersonEntity.self, "Configuration1"))
```
- parameter entityClass: the `NSManagedObject` class type to be created
- parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration.
*/
@@ -133,12 +128,22 @@ public struct Into<T: NSManagedObject>: Hashable {
CoreStore.assert(
entityClass is T.Type,
"Attempted to create generic type \(cs_typeName(Into<T>)) with entity class \(cs_typeName(entityClass))"
"Attempted to create generic type \(cs_typeName(Into<T>.self)) with entity class \(cs_typeName(entityClass))"
)
self.init(entityClass: entityClass, configuration: configuration, inferStoreIfPossible: false)
}
// MARK: Equatable
public static func == <T: NSManagedObject, U: NSManagedObject>(lhs: Into<T>, rhs: Into<U>) -> Bool {
return lhs.entityClass == rhs.entityClass
&& lhs.configuration == rhs.configuration
&& lhs.inferStoreIfPossible == rhs.inferStoreIfPossible
}
// MARK: Hashable
public var hashValue: Int {
@@ -177,22 +182,3 @@ public struct Into<T: NSManagedObject>: Hashable {
self.inferStoreIfPossible = inferStoreIfPossible
}
}
// MARK: - Into: Equatable
@warn_unused_result
public func == <T: NSManagedObject, U: NSManagedObject>(lhs: Into<T>, rhs: Into<U>) -> Bool {
return lhs.entityClass == rhs.entityClass
&& lhs.configuration == rhs.configuration
&& lhs.inferStoreIfPossible == rhs.inferStoreIfPossible
}
@warn_unused_result
public func != <T: NSManagedObject, U: NSManagedObject>(lhs: Into<T>, rhs: Into<U>) -> Bool {
return lhs.entityClass == rhs.entityClass
&& lhs.configuration == rhs.configuration
&& lhs.inferStoreIfPossible == rhs.inferStoreIfPossible
}

View File

@@ -48,17 +48,17 @@ public extension NSManagedObject {
// MARK: Internal
@nonobjc
internal class func createInContext(context: NSManagedObjectContext) -> Self {
internal class func createInContext(_ context: NSManagedObjectContext) -> Self {
return self.init(
entity: context.entityDescriptionForEntityType(self)!,
insertIntoManagedObjectContext: context
insertInto: context
)
}
@nonobjc
internal func deleteFromContext() {
self.managedObjectContext?.deleteObject(self)
self.managedObjectContext?.delete(self)
}
}

View File

@@ -49,9 +49,9 @@ import Foundation
// ...
let result = transaction.commit()
switch result {
case .Success(let hasChanges):
case .success(let hasChanges):
// hasChanges indicates if there were changes or not
case .Failure(let error):
case .failure(let error):
// error is a CoreStoreError enum value
}
}
@@ -60,14 +60,45 @@ import Foundation
public enum SaveResult: Hashable {
/**
`SaveResult.Success` indicates that the `commit()` for the transaction succeeded, either because the save succeeded or because there were no changes to save. The associated value `hasChanges` indicates if there were saved changes or not.
`SaveResult.success` indicates that the `commit()` for the transaction succeeded, either because the save succeeded or because there were no changes to save. The associated value `hasChanges` indicates if there were saved changes or not.
*/
case Success(hasChanges: Bool)
case success(hasChanges: Bool)
/**
`SaveResult.Failure` indicates that the `commit()` for the transaction failed. The associated object for this value is a `CoreStoreError` enum value.
`SaveResult.failure` indicates that the `commit()` for the transaction failed. The associated object for this value is a `CoreStoreError` enum value.
*/
case Failure(CoreStoreError)
case failure(CoreStoreError)
/**
Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
*/
public var boolValue: Bool {
switch self {
case .success: return true
case .failure: return false
}
}
// MARK: Equatable
public static func == (lhs: SaveResult, rhs: SaveResult) -> Bool {
switch (lhs, rhs) {
case (.success(let hasChanges1), .success(let hasChanges2)):
return hasChanges1 == hasChanges2
case (.failure(let error1), .failure(let error2)):
return error1 == error2
default:
return false
}
}
// MARK: Hashable
@@ -76,10 +107,10 @@ public enum SaveResult: Hashable {
switch self {
case .Success(let hasChanges):
case .success(let hasChanges):
return self.boolValue.hashValue ^ hasChanges.hashValue
case .Failure(let error):
case .failure(let error):
return self.boolValue.hashValue ^ error.hashValue
}
}
@@ -89,45 +120,11 @@ public enum SaveResult: Hashable {
internal init(hasChanges: Bool) {
self = .Success(hasChanges: hasChanges)
self = .success(hasChanges: hasChanges)
}
internal init(_ error: CoreStoreError) {
self = .Failure(error)
}
}
// MARK: - SaveResult: BooleanType
extension SaveResult: BooleanType {
public var boolValue: Bool {
switch self {
case .Success: return true
case .Failure: return false
}
}
}
// MARK: - SaveResult: Equatable
@warn_unused_result
public func == (lhs: SaveResult, rhs: SaveResult) -> Bool {
switch (lhs, rhs) {
case (.Success(let hasChanges1), .Success(let hasChanges2)):
return hasChanges1 == hasChanges2
case (.Failure(let error1), .Failure(let error2)):
return error1 == error2
default:
return false
self = .failure(error)
}
}

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - SynchronousDataTransaction
@@ -46,7 +43,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
public func commitAndWait() -> SaveResult {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to commit a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -91,10 +88,11 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter closure: the block where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- returns: a `SaveResult` value indicating success or failure, or `nil` if the transaction was not comitted synchronously
*/
public func beginSynchronous(closure: (transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
@discardableResult
public func beginSynchronous(_ closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) -> SaveResult? {
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
self.transactionQueue.cs_isCurrentExecutionContext(),
"Attempted to begin a child transaction from a \(cs_typeName(self)) outside its designated queue."
)
CoreStore.assert(
@@ -117,11 +115,11 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter into: the `Into` clause indicating the destination `NSManagedObject` entity type and the destination configuration
- returns: a new `NSManagedObject` instance of the specified entity type.
*/
public override func create<T: NSManagedObject>(into: Into<T>) -> T {
public override func create<T: NSManagedObject>(_ into: Into<T>) -> T {
CoreStore.assert(
!self.isCommitted,
"Attempted to create an entity of type \(cs_typeName(T)) from an already committed \(cs_typeName(self))."
"Attempted to create an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
)
return super.create(into)
@@ -133,8 +131,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public override func edit<T: NSManagedObject>(object: T?) -> T? {
public override func edit<T: NSManagedObject>(_ object: T?) -> T? {
CoreStore.assert(
!self.isCommitted,
@@ -151,12 +148,11 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter objectID: the `NSManagedObjectID` for the object to be edited
- returns: an editable proxy for the specified `NSManagedObject`.
*/
@warn_unused_result
public override func edit<T: NSManagedObject>(into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
public override func edit<T: NSManagedObject>(_ into: Into<T>, _ objectID: NSManagedObjectID) -> T? {
CoreStore.assert(
!self.isCommitted,
"Attempted to update an entity of type \(cs_typeName(T)) from an already committed \(cs_typeName(self))."
"Attempted to update an entity of type \(cs_typeName(into.entityClass)) from an already committed \(cs_typeName(self))."
)
return super.edit(into, objectID)
@@ -167,7 +163,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter object: the `NSManagedObject` type to be deleted
*/
public override func delete(object: NSManagedObject?) {
public override func delete(_ object: NSManagedObject?) {
CoreStore.assert(
!self.isCommitted,
@@ -184,7 +180,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter object2: another `NSManagedObject` to be deleted
- parameter objects: other `NSManagedObject`s to be deleted
*/
public override func delete(object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
public override func delete(_ object1: NSManagedObject?, _ object2: NSManagedObject?, _ objects: NSManagedObject?...) {
CoreStore.assert(
!self.isCommitted,
@@ -199,7 +195,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
- parameter objects: the `NSManagedObject`s to be deleted
*/
public override func delete<S: SequenceType where S.Generator.Element: NSManagedObject>(objects: S) {
public override func delete<S: Sequence>(_ objects: S) where S.Iterator.Element: NSManagedObject {
CoreStore.assert(
!self.isCommitted,
@@ -212,7 +208,7 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
// MARK: Internal
internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, closure: (transaction: SynchronousDataTransaction) -> Void) {
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, closure: @escaping (_ transaction: SynchronousDataTransaction) -> Void) {
self.closure = closure
@@ -223,12 +219,12 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
self.transactionQueue.sync {
self.closure(transaction: self)
self.closure(self)
if !self.isCommitted && self.hasChanges {
CoreStore.log(
.Warning,
.warning,
message: "The closure for the \(cs_typeName(self)) completed without being committed. All changes made within the transaction were discarded."
)
}
@@ -239,29 +235,5 @@ public final class SynchronousDataTransaction: BaseDataTransaction {
// MARK: Private
private let closure: (transaction: SynchronousDataTransaction) -> Void
// MARK: Deprecated
@available(*, deprecated=1.3.4, obsoleted=2.0.0, message="Resetting the context is inherently unsafe. This method will be removed in the near future. Use `beginUnsafe()` to create transactions with `undo` support.")
public func rollback() {
CoreStore.assert(
!self.isCommitted,
"Attempted to rollback an already committed \(cs_typeName(self))."
)
CoreStore.assert(
self.transactionQueue.isCurrentExecutionContext(),
"Attempted to rollback a \(cs_typeName(self)) outside its designated queue."
)
self.context.reset()
}
@available(*, deprecated=1.5.2, obsoleted=2.0.0, renamed="commitAndWait")
public func commit() {
self.commitAndWait()
}
private let closure: (_ transaction: SynchronousDataTransaction) -> Void
}

View File

@@ -25,9 +25,6 @@
import Foundation
import CoreData
#if USE_FRAMEWORKS
import GCDKit
#endif
// MARK: - UnsafeDataTransaction
@@ -42,12 +39,12 @@ public final class UnsafeDataTransaction: BaseDataTransaction {
- parameter completion: the block executed after the save completes. Success or failure is reported by the `SaveResult` argument of the block.
*/
public func commit(completion: (result: SaveResult) -> Void) {
public func commit(_ completion: @escaping (_ result: SaveResult) -> Void) {
self.context.saveAsynchronouslyWithCompletion { (result) -> Void in
self.result = result
completion(result: result)
completion(result)
}
}
@@ -105,7 +102,7 @@ public final class UnsafeDataTransaction: BaseDataTransaction {
- parameter closure: the closure where changes can be made prior to the flush
- throws: an error thrown from `closure`, or an error thrown by Core Data (usually validation errors or conflict errors)
*/
public func flush(@noescape closure: () throws -> Void) rethrows {
public func flush(closure: () throws -> Void) rethrows {
try closure()
self.context.processPendingChanges()
@@ -129,8 +126,7 @@ public final class UnsafeDataTransaction: BaseDataTransaction {
- prameter supportsUndo: `undo()`, `redo()`, and `rollback()` methods are only available when this parameter is `true`, otherwise those method will raise an exception. Defaults to `false`. Note that turning on Undo support may heavily impact performance especially on iOS or watchOS where memory is limited.
- returns: an `UnsafeDataTransaction` instance where creates, updates, and deletes can be made.
*/
@warn_unused_result
public func beginUnsafe(supportsUndo supportsUndo: Bool = false) -> UnsafeDataTransaction {
public func beginUnsafe(supportsUndo: Bool = false) -> UnsafeDataTransaction {
return UnsafeDataTransaction(
mainContext: self.context,
@@ -139,39 +135,20 @@ public final class UnsafeDataTransaction: BaseDataTransaction {
)
}
/**
Returns the `NSManagedObjectContext` for this unsafe transaction. Use only for cases where external frameworks need an `NSManagedObjectContext` instance to work with.
- Important: It is the developer's responsibility to ensure the following:
- that the `UnsafeDataTransaction` that owns this context should be strongly referenced and prevented from being deallocated during the context's lifetime
- that all saves will be done either through the `UnsafeDataTransaction`'s `commit(...)` method, or by calling `save()` manually on the context, its parent, and all other ancestor contexts if there are any.
*/
public var internalContext: NSManagedObjectContext {
return self.context
}
// MARK: Internal
internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, supportsUndo: Bool) {
internal init(mainContext: NSManagedObjectContext, queue: DispatchQueue, supportsUndo: Bool) {
super.init(mainContext: mainContext, queue: queue, supportsUndo: supportsUndo, bypassesQueueing: true)
}
// MARK: Deprecated
// MARK: Obsolete
@available(*, deprecated=1.3.1, obsoleted=2.0.0, renamed="beginUnsafe")
@warn_unused_result
public func beginDetached() -> UnsafeDataTransaction {
@available(*, obsoleted: 3.0.0, message: "Transaction contexts are now exposed through the FetchableSource and QueryableSource protocols.", renamed: "internalContext()")
public var internalContext: NSManagedObjectContext {
return self.beginUnsafe()
fatalError()
}
}
// MARK: Deprecated
@available(*, deprecated=1.3.1, obsoleted=2.0.0, renamed="UnsafeDataTransaction")
public typealias DetachedDataTransaction = UnsafeDataTransaction