             _managedObjectContext = value
         }
     }
-    var writeObjectContext: NSManagedObjectContext?
-    var writeSemaphore: dispatch_semaphore_t?
-    
+    private var writeObjectContext: NSManagedObjectContext?
+
     static var moc: NSManagedObjectContext {
         get {
             if DataController.shared.managedObjectContext == nil {

        return NSEntityDescription.insertNewObjectForEntityForName(model, inManagedObjectContext: DataController.moc)
    }
    
    // Writes could still be executed on main thread, but recommended to use DataController.write {...}
    static func saveContext() {
        dispatch_async(CoreDataWriteQueue) {
            guard let managedObjectContext: NSManagedObjectContext = DataController.shared.managedObjectContext else {
                return
            }
            
            if managedObjectContext.hasChanges {
                do {
                    try managedObjectContext.save()
                }
                catch {
                    fatalError("Error saving DB: \(error)")
                }
            }
        }
    }

        }
    }

    private func mainThreadContext() -> NSManagedObjectContext {
        if _managedObjectContext != nil {
            return _managedObjectContext!
        }

        // do not set a persistent store for main thread context.
        // The parent of the main context is the writeContext, and when the main context is saved
        // the mainThreadContextDidSave

        managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
        managedObjectContext?.undoManager = nil
        managedObjectContext?.mergePolicy = NSErrorMergePolicy
        managedObjectContext?.parentContext = writeContext()

        // when main context is saved, we need to propagate the changes to our insertion thread's context
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(mainThreadContextDidSaveInMem(_:)), name: NSManagedObjectContextDidSaveNotification, object: managedObjectContext!)

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(bgContextDidSaveToDisk(_:)), name: NSManagedObjectContextDidSaveNotification, object: writeContext())

        return managedObjectContext!
    }

    @objc private func bgContextDidSaveToDisk(notification: NSNotification) {
        assert(!NSThread.isMainThread())
        postAsyncToMain {
            self.managedObjectContext?.mergeChangesFromContextDidSaveNotification(notification)
        }
    }

    @objc private func mainThreadContextDidSaveInMem(notification: NSNotification) {
        assert(NSThread.isMainThread())
        dispatch_async(CoreDataWriteQueue, {
            self.writeObjectContext?.mergeChangesFromContextDidSaveNotification(notification)
            DataController.saveContext()
        })
    }
    
    private func writeContext() -> NSManagedObjectContext {
        // This will only ever be called from a dispatch thread.
        if writeObjectContext == nil {
            writeObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
            writeObjectContext?.persistentStoreCoordinator = persistentStoreCoordinator
            writeObjectContext?.undoManager = nil
            writeObjectContext?.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
        }
        return writeObjectContext!
    }
    
    // To be called only from the main thread.
    @objc private func mergeSaveNotification(notification: NSNotification) {
        managedObjectContext?.mergeChangesFromContextDidSaveNotification(notification)
    }
}
