allow nested transactions

This commit is contained in:
John Rommel Estropia
2015-02-28 00:55:22 +09:00
parent c71198347d
commit a45c94dd52
9 changed files with 62 additions and 20 deletions

View File

@@ -73,7 +73,6 @@ public class DataStack {
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
self.mainContext = NSManagedObjectContext.mainContextForRootContext(self.rootSavingContext)
self.transactionQueue = .createSerial("com.hardcoredata.datastack.transactionqueue")
self.entityNameMapping = (managedObjectModel.entities as! [NSEntityDescription]).reduce([EntityClassNameType: EntityNameType]()) { (var mapping, entityDescription) in
if let entityName = entityDescription.name {
@@ -269,7 +268,7 @@ public class DataStack {
// MARK: Internal
internal let mainContext: NSManagedObjectContext
internal let transactionQueue: GCDQueue;
internal let transactionQueue: GCDQueue = .createSerial("com.hardcoredata.datastack.transactionqueue")
internal func entityNameForEntityClass(entityClass: NSManagedObject.Type) -> String? {

View File

@@ -37,10 +37,6 @@ public final class DataTransaction {
// MARK: - Public
/**
The background concurrent context managed by the transaction.
*/
public let context: NSManagedObjectContext
// MARK: Object management
@@ -129,9 +125,25 @@ public final class DataTransaction {
self.result = self.context.saveSynchronously()
}
/**
Begins a child transaction synchronously where NSManagedObject creates, updates, and deletes can be made.
:param: 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 performTransactionAndWait(closure: (transaction: DataTransaction) -> Void) -> SaveResult? {
return DataTransaction(
mainContext: self.context,
queue: self.childTransactionQueue,
closure: closure).performAndWait()
}
// MARK: - Internal
internal let context: NSManagedObjectContext
internal init(mainContext: NSManagedObjectContext, queue: GCDQueue, closure: (transaction: DataTransaction) -> Void) {
self.transactionQueue = queue
@@ -168,4 +180,6 @@ public final class DataTransaction {
private var result: SaveResult?
private let transactionQueue: GCDQueue
private let closure: (transaction: DataTransaction) -> Void
private lazy var childTransactionQueue: GCDQueue = .createSerial("com.hardcoredata.datastack.childtransactionqueue")
}

View File

@@ -30,24 +30,24 @@ import Foundation
public final class DefaultLogger: HardcoreDataLogger {
public func log(#level: LogLevel, message: String, fileName: StaticString, lineNumber: UWord, functionName: StaticString) {
public func log(#level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
#if DEBUG
Swift.println("[HardcoreData] \(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n")
#endif
}
public func handleError(#error: NSError, message: String, fileName: StaticString, lineNumber: UWord, functionName: StaticString) {
public func handleError(#error: NSError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
#if DEBUG
Swift.println("[HardcoreData] \(fileName.stringValue.lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message): \(error)\n")
#endif
}
public func assert(@autoclosure condition: () -> Bool, message: String, fileName: StaticString, lineNumber: UWord, functionName: StaticString) {
public func assert(@autoclosure condition: () -> Bool, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
#if DEBUG
Swift.assert(condition, message, file: fileName, line: lineNumber)
Swift.assert(condition, message, file: fileName, line: numericCast(lineNumber))
#endif
}
}

View File

@@ -78,7 +78,7 @@ public enum HardcoreData {
// MARK: Internal
internal static func log(level: LogLevel, message: String, fileName: StaticString = __FILE__, lineNumber: UWord = __LINE__, functionName: StaticString = __FUNCTION__) {
internal static func log(level: LogLevel, message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) {
self.logger.log(
level: level,
@@ -91,7 +91,7 @@ public enum HardcoreData {
)
}
internal static func handleError(error: NSError, _ message: String, fileName: StaticString = __FILE__, lineNumber: UWord = __LINE__, functionName: StaticString = __FUNCTION__) {
internal static func handleError(error: NSError, _ message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) {
self.logger.handleError(
error: error,
@@ -101,7 +101,7 @@ public enum HardcoreData {
functionName: functionName)
}
internal static func assert(@autoclosure condition: () -> Bool, _ message: String, fileName: StaticString = __FILE__, lineNumber: UWord = __LINE__, functionName: StaticString = __FUNCTION__) {
internal static func assert(@autoclosure condition: () -> Bool, _ message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) {
self.logger.assert(
condition,

View File

@@ -41,9 +41,9 @@ public enum LogLevel {
public protocol HardcoreDataLogger {
func log(#level: LogLevel, message: String, fileName: StaticString, lineNumber: UWord, functionName: StaticString)
func log(#level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
func handleError(#error: NSError, message: String, fileName: StaticString, lineNumber: UWord, functionName: StaticString)
func handleError(#error: NSError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
func assert(@autoclosure condition: () -> Bool, message: String, fileName: StaticString, lineNumber: UWord, functionName: StaticString)
func assert(@autoclosure condition: () -> Bool, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
}

View File

@@ -41,11 +41,12 @@ internal extension NSManagedObjectContext {
return parentContext.parentStack
}
return self.getAssociatedObjectForKey(&PropertyKeys.parentStack)
}
set {
if let parentContext = self.parentContext {
if self.parentContext != nil {
return
}

View File

@@ -54,7 +54,7 @@ internal extension NSManagedObjectContext {
context.parentContext = self
context.parentStack = self.parentStack
context.setupForHardcoreDataWithContextName("com.hardcoredata.temporarycontext")
context.shouldCascadeSavesToParent = true
context.shouldCascadeSavesToParent = (self.concurrencyType == .MainQueueConcurrencyType)
return context
}
@@ -67,7 +67,6 @@ internal extension NSManagedObjectContext {
if !self.hasChanges {
self.reset()
return
}