mirror of
https://github.com/modo-studio/SugarRecord.git
synced 2024-09-11 14:36:41 +03:00
Improved contexts stack implementation
This commit is contained in:
parent
d111aae2f2
commit
a92236a19d
@ -30,25 +30,30 @@ class SugarRecord {
|
||||
// Initialize Database
|
||||
class func setupCoreDataStack (automigrating: Bool?, databaseName: String?) -> () {
|
||||
// Checking the coordinator doesn't exist
|
||||
if let psc = NSPersistentStoreCoordinator.defaultPersistentStoreCoordinator(){}
|
||||
else {
|
||||
var psc: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator.defaultPersistentStoreCoordinator()
|
||||
if psc == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Initializing persistentStoreCoordinator
|
||||
var psc: NSPersistentStoreCoordinator
|
||||
if let dbName = databaseName {
|
||||
psc = NSPersistentStoreCoordinator.newCoordinator(dbName, automigrating: automigrating)
|
||||
if databaseName != nil {
|
||||
psc = NSPersistentStoreCoordinator.newCoordinator(databaseName!, automigrating: automigrating)
|
||||
}
|
||||
else {
|
||||
psc = NSPersistentStoreCoordinator.newCoordinator(self.defaultDatabaseName(), automigrating: automigrating)
|
||||
}
|
||||
NSPersistentStoreCoordinator.setDefaultPersistentStoreCoordinator(psc)
|
||||
|
||||
// Setting as default persistent store coordinator
|
||||
NSPersistentStoreCoordinator.setDefaultPersistentStoreCoordinator(psc!)
|
||||
|
||||
// Initialize stack
|
||||
NSManagedObjectContext.initializeContextsStack(psc!)
|
||||
}
|
||||
|
||||
|
||||
// CleanUp
|
||||
class func cleanUp () -> () {
|
||||
|
||||
NSManagedObjectContext.cleanUp()
|
||||
}
|
||||
|
||||
// Returns current stack information
|
||||
@ -94,30 +99,109 @@ extension NSManagedObjectContext {
|
||||
return Static.rootSavingContext
|
||||
}
|
||||
|
||||
// Root Saving Context Setter
|
||||
class func setRootSavingContext(context: NSManagedObjectContext?) {
|
||||
Static.rootSavingContext = context
|
||||
}
|
||||
|
||||
// Default Context Getter
|
||||
class func defaultContext() -> (NSManagedObjectContext?) {
|
||||
return Static.defaultContext
|
||||
}
|
||||
|
||||
// Returns a new context with default context as parent
|
||||
class func newContext (parentContext: NSManagedObjectContext?) -> (NSManagedObjectContext) {
|
||||
var context: NSManagedObjectContext = NSManagedObjectContext()
|
||||
context.parentContext = self.defaultContext()!
|
||||
return context
|
||||
// Default Context Setter
|
||||
class func setDefaultContext(context: NSManagedObjectContext?) {
|
||||
Static.defaultContext = context
|
||||
}
|
||||
|
||||
// Returns a new context with a given context as a parent
|
||||
class func newContextWithPersistentStoreCoordinator(persistentStoreCoordinator: NSPersistentStoreCoordinator) -> (NSManagedObjectContext){
|
||||
return self.newContext(nil, persistentStoreCoordinator: persistentStoreCoordinator)
|
||||
}
|
||||
|
||||
// Returns a new context with a given context as a parent
|
||||
class func newContextWithParentContext(parentContext: NSManagedObjectContext) -> (NSManagedObjectContext){
|
||||
return self.newContext(parentContext, persistentStoreCoordinator: nil)
|
||||
}
|
||||
|
||||
// Returns a new context with a parent context or persistentStoreCoordinator
|
||||
class func newContext (parentContext: NSManagedObjectContext?, persistentStoreCoordinator: NSPersistentStoreCoordinator?) -> (NSManagedObjectContext) {
|
||||
var newContext: NSManagedObjectContext?
|
||||
if parentContext != nil {
|
||||
newContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
|
||||
newContext?.parentContext = self.defaultContext()!
|
||||
}
|
||||
else if persistentStoreCoordinator != nil {
|
||||
newContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
|
||||
newContext?.persistentStoreCoordinator = persistentStoreCoordinator
|
||||
}
|
||||
else {
|
||||
assert(true, "SUGAR-RECORD: Either parentContext or persistentStoreCoordinator has to be passed")
|
||||
}
|
||||
println("SUGAR-RECORD: Created new context - \(newContext)")
|
||||
return newContext!
|
||||
}
|
||||
|
||||
// Initialize default contexts stack
|
||||
class func initializeContextsStack (persistentStoreCoordinator: NSPersistentStoreCoordinator) {
|
||||
var rootContext: NSManagedObjectContext = self.newContext(nil, persistentStoreCoordinator: persistentStoreCoordinator)
|
||||
self.setRootSavingContext(rootSavingContext())
|
||||
var defaultContext: NSManagedObjectContext = self.newContext(rootContext, persistentStoreCoordinator: nil)
|
||||
}
|
||||
|
||||
// CleanUp
|
||||
class func cleanUp () -> () {
|
||||
self.setRootSavingContext(nil)
|
||||
self.setDefaultContext(nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//MARK - NSManagedObject Extension
|
||||
|
||||
extension NSManagedObjectModel {
|
||||
// Static variables
|
||||
struct Static {
|
||||
static var defaultManagedObjectModel: NSManagedObjectModel? = nil
|
||||
}
|
||||
|
||||
class func setDefaultManagedObjectModel(objectModel: NSManagedObjectModel) {
|
||||
Static.defaultManagedObjectModel = objectModel
|
||||
}
|
||||
class func defaultManagedObjectModel() -> (defaultManagedObjectModel: NSManagedObjectModel?) {
|
||||
var currentModel: NSManagedObjectModel? = Static.defaultManagedObjectModel
|
||||
if currentModel == nil {
|
||||
currentModel = self.mergedModelFromBundles(nil)
|
||||
self.setDefaultManagedObjectModel(currentModel!)
|
||||
}
|
||||
return currentModel
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
if (defaultManagedObjectModel_ == nil && [MagicalRecord shouldAutoCreateManagedObjectModel])
|
||||
{
|
||||
[self MR_setDefaultManagedObjectModel:[self MR_mergedObjectModelFromMainBundle]];
|
||||
}
|
||||
return defaultManagedObjectModel_;
|
||||
|
||||
+ (NSManagedObjectModel *) MR_mergedObjectModelFromMainBundle;
|
||||
{
|
||||
return [self mergedModelFromBundles:nil];
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// MARK - NSManagedObject Extension
|
||||
|
||||
extension NSManagedObject {
|
||||
class func defaultManagedObject () -> (NSManagedObject?) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
class func filter (context: NSManagedObjectContext?, predicate: NSPredicate) -> (NSArray) {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -126,12 +210,10 @@ extension NSManagedObject {
|
||||
* @param NSPredicate To filter fetch results
|
||||
* @return Int with the count
|
||||
*/
|
||||
class func count(context: NSManagedObjectContext?, predicate: NSPredicate) -> (count: Int) {
|
||||
class func count(context: NSManagedObjectContext?, predicate: NSPredicate) -> (count: Int?) {
|
||||
return self.filter(context, predicate: predicate).count
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -151,10 +233,24 @@ extension NSPersistentStoreCoordinator {
|
||||
|
||||
|
||||
// Coordinator initializer
|
||||
class func newCoordinator (databaseName: String, automigrating: Bool?) -> (NSPersistentStoreCoordinator) {
|
||||
class func newCoordinator (databaseName: String, automigrating: Bool?) -> (NSPersistentStoreCoordinator?) {
|
||||
var model: NSManagedObjectModel = NSManagedObjectModel.defaultManagedObjectModel()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/*NSManagedObjectModel *model = [NSManagedObjectModel MR_defaultManagedObjectModel];
|
||||
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
|
||||
|
||||
[coordinator MR_addAutoMigratingSqliteStoreNamed:storeFileName];
|
||||
|
||||
//HACK: lame solution to fix automigration error "Migration failed after first pass"
|
||||
if ([[coordinator persistentStores] count] == 0)
|
||||
{
|
||||
[coordinator performSelector:@selector(MR_addAutoMigratingSqliteStoreNamed:) withObject:storeFileName afterDelay:0.5];
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
3DBC55F4198E826E00268EB3 /* SugarRecordTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBC55F3198E826E00268EB3 /* SugarRecordTests.swift */; };
|
||||
3DBC55FF198E82F500268EB3 /* SugarRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBC55FE198E82F500268EB3 /* SugarRecord.swift */; };
|
||||
3DBC5603198E844B00268EB3 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DBC5602198E844B00268EB3 /* CoreData.framework */; };
|
||||
3DD010AF1990379D00673854 /* SugarRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBC55FE198E82F500268EB3 /* SugarRecord.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -64,7 +65,6 @@
|
||||
3DBC55CF198E826E00268EB3 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3DBC5602198E844B00268EB3 /* CoreData.framework */,
|
||||
3DBC55DA198E826E00268EB3 /* SugarRecord */,
|
||||
3DBC55F0198E826E00268EB3 /* SugarRecordTests */,
|
||||
3DBC55D9198E826E00268EB3 /* Products */,
|
||||
@ -83,6 +83,7 @@
|
||||
3DBC55DA198E826E00268EB3 /* SugarRecord */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3DD010AE1990378200673854 /* Frameworks */,
|
||||
3DBC55FD198E82E300268EB3 /* SugarRecord */,
|
||||
3DBC55DD198E826E00268EB3 /* AppDelegate.swift */,
|
||||
3DBC55E2198E826E00268EB3 /* ViewController.swift */,
|
||||
@ -128,6 +129,14 @@
|
||||
path = ../../SugarRecord;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3DD010AE1990378200673854 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3DBC5602198E844B00268EB3 /* CoreData.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -238,6 +247,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3DD010AF1990379D00673854 /* SugarRecord.swift in Sources */,
|
||||
3DBC55F4198E826E00268EB3 /* SugarRecordTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -14,9 +14,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
var name: String! = nil
|
||||
println(name)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -41,95 +42,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
func applicationWillTerminate(application: UIApplication!) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
// Saves changes in the application's managed object context before the application terminates.
|
||||
self.saveContext()
|
||||
}
|
||||
|
||||
func saveContext () {
|
||||
var error: NSError? = nil
|
||||
let managedObjectContext = self.managedObjectContext
|
||||
if managedObjectContext != nil {
|
||||
if managedObjectContext.hasChanges && !managedObjectContext.save(&error) {
|
||||
// Replace this implementation with code to handle the error appropriately.
|
||||
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
||||
//println("Unresolved error \(error), \(error.userInfo)")
|
||||
abort()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #pragma mark - Core Data stack
|
||||
|
||||
// Returns the managed object context for the application.
|
||||
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
|
||||
var managedObjectContext: NSManagedObjectContext {
|
||||
if !_managedObjectContext {
|
||||
let coordinator = self.persistentStoreCoordinator
|
||||
if coordinator != nil {
|
||||
_managedObjectContext = NSManagedObjectContext()
|
||||
_managedObjectContext!.persistentStoreCoordinator = coordinator
|
||||
}
|
||||
}
|
||||
return _managedObjectContext!
|
||||
}
|
||||
var _managedObjectContext: NSManagedObjectContext? = nil
|
||||
|
||||
// Returns the managed object model for the application.
|
||||
// If the model doesn't already exist, it is created from the application's model.
|
||||
var managedObjectModel: NSManagedObjectModel {
|
||||
if !_managedObjectModel {
|
||||
let modelURL = NSBundle.mainBundle().URLForResource("SugarRecord", withExtension: "momd")
|
||||
_managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)
|
||||
}
|
||||
return _managedObjectModel!
|
||||
}
|
||||
var _managedObjectModel: NSManagedObjectModel? = nil
|
||||
|
||||
// Returns the persistent store coordinator for the application.
|
||||
// If the coordinator doesn't already exist, it is created and the application's store added to it.
|
||||
var persistentStoreCoordinator: NSPersistentStoreCoordinator {
|
||||
if !_persistentStoreCoordinator {
|
||||
let storeURL = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SugarRecord.sqlite")
|
||||
var error: NSError? = nil
|
||||
_persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
|
||||
if _persistentStoreCoordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil, error: &error) == nil {
|
||||
/*
|
||||
Replace this implementation with code to handle the error appropriately.
|
||||
|
||||
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
||||
|
||||
Typical reasons for an error here include:
|
||||
* The persistent store is not accessible;
|
||||
* The schema for the persistent store is incompatible with current managed object model.
|
||||
Check the error message to determine what the actual problem was.
|
||||
|
||||
|
||||
If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
|
||||
|
||||
If you encounter schema incompatibility errors during development, you can reduce their frequency by:
|
||||
* Simply deleting the existing store:
|
||||
NSFileManager.defaultManager().removeItemAtURL(storeURL, error: nil)
|
||||
|
||||
* Performing automatic lightweight migration by passing the following dictionary as the options parameter:
|
||||
[NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
|
||||
|
||||
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
|
||||
|
||||
*/
|
||||
//println("Unresolved error \(error), \(error!.userInfo)")
|
||||
abort()
|
||||
}
|
||||
}
|
||||
return _persistentStoreCoordinator!
|
||||
}
|
||||
var _persistentStoreCoordinator: NSPersistentStoreCoordinator? = nil
|
||||
|
||||
// #pragma mark - Application's Documents directory
|
||||
|
||||
// Returns the URL to the application's Documents directory.
|
||||
var applicationDocumentsDirectory: NSURL {
|
||||
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
|
||||
return urls[urls.count-1] as NSURL
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -8,19 +8,23 @@
|
||||
|
||||
import UIKit
|
||||
import XCTest
|
||||
import SugarRecord
|
||||
|
||||
class SugarRecordTests: XCTestCase {
|
||||
class SugarRecordSetupTests: XCTestCase {
|
||||
var sugarRecord: SugarRecord?
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
sugarRecord = SugarRecord()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func testExample() {
|
||||
// This is an example of a functional test case.
|
||||
XCTAssert(true, "Pass")
|
||||
@ -32,5 +36,4 @@ class SugarRecordTests: XCTestCase {
|
||||
// Put the code you want to measure the time of here.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user