Reputation: 31283
I use MagicalRecord to work with core data.
I have a separate class called DatabaseManager
to handle core data related tasks. I have a initializer accepting a NSManagedObjectContext
object.
import CoreData
import Foundation
import MagicalRecord
import SwiftyJSON
public class DatabaseManager {
private let context: NSManagedObjectContext!
init(context: NSManagedObjectContext) {
self.context = context
}
public func insertReports(data: AnyObject, success: () -> Void, failure: (error: NSError?) -> Void) {
MagicalRecord.cleanUp()
MagicalRecord.setupCoreDataStackWithStoreNamed("Records")
let json = JSON(data)
if let reports = json.array {
for reportObj in reports {
let report = Report.MR_createInContext(context) as Report
report.id = reportObj["Id"].int
report.type = reportObj["Type"].string!
}
context.MR_saveToPersistentStoreAndWait()
success()
}
}
private func getReport(id: Int) -> Report {
let idFilter = NSPredicate(format: "id == %@", NSNumber(integer: id))
let fetchRequest = Report.MR_requestAllWithPredicate(idFilter, inContext: context)
return Report.MR_executeFetchRequestAndReturnFirstObject(fetchRequest, inContext: context) as Report
}
}
And I initialize the class and call it's insertReports()
method to insert some records into core data.
let context = NSManagedObjectContext.MR_defaultContext()
let dbManager = DatabaseManager(context: context)
getReportsFromAPI({ (data) -> Void in
dbManager.insertReports(data, success: { () -> Void in
println("Reports added successfully")
}, failure: { (error) -> Void in
println("Error inserting Reports: \(error?.localizedDescription)")
})
}, failure: { (error) -> Void in
println("Error getting Reports from API: \(error?.localizedDescription)")
})
But this doesn't seem to work. I get the following output in the console.
2015-03-05 00:39:39.412 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setDefaultContext:](0x104396400) Set Default Context: (null)
2015-03-05 00:39:39.412 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setRootSavingContext:](0x104396400) Set Root Saving Context: (null)
2015-03-05 00:39:39.583 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_contextWithStoreCoordinator:](0x104396400) -> Created Context UNNAMED
2015-03-05 00:39:39.584 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setRootSavingContext:](0x104396400) Set Root Saving Context: <NSManagedObjectContext: 0x7f81b04c6b00>
2015-03-05 00:39:39.584 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_newMainQueueContext](0x104396400) Created Main Queue Context: <NSManagedObjectContext: 0x7f81b04c75a0>
2015-03-05 00:39:39.584 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setDefaultContext:](0x104396400) Set Default Context: <NSManagedObjectContext: 0x7f81b04c75a0>
2015-03-05 00:39:40.434 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setDefaultContext:](0x104396400) Set Default Context: (null)
2015-03-05 00:39:40.434 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setRootSavingContext:](0x104396400) Set Root Saving Context: (null)
2015-03-05 00:39:40.435 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setDefaultContext:](0x104396400) Set Default Context: (null)
2015-03-05 00:39:40.435 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setRootSavingContext:](0x104396400) Set Root Saving Context: (null)
2015-03-05 00:39:40.443 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_contextWithStoreCoordinator:](0x104396400) -> Created Context UNNAMED
2015-03-05 00:39:40.443 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setRootSavingContext:](0x104396400) Set Root Saving Context: <NSManagedObjectContext: 0x7f81b280e5a0>
2015-03-05 00:39:40.444 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_newMainQueueContext](0x104396400) Created Main Queue Context: <NSManagedObjectContext: 0x7f81b04d76c0>
2015-03-05 00:39:40.444 Reports[7123:967179] +[NSManagedObjectContext(MagicalRecord) MR_setDefaultContext:](0x104396400) Set Default Context: <NSManagedObjectContext: 0x7f81b04d76c0>
2015-03-05 00:39:40.446 Reports[7123:967179] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7f81b04c75a0) → Saving <NSManagedObjectContext (0x7f81b04c75a0): *** DEFAULT ***> on *** MAIN THREAD ***
2015-03-05 00:39:40.446 Reports[7123:967179] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7f81b04c75a0) → Save Parents? 1
2015-03-05 00:39:40.447 Reports[7123:967179] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7f81b04c75a0) → Save Synchronously? 1
2015-03-05 00:39:40.448 Reports[7123:967179] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7f81b04c6b00) → Saving <NSManagedObjectContext (0x7f81b04c6b00): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
2015-03-05 00:39:40.448 Reports[7123:967179] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7f81b04c6b00) → Save Parents? 1
2015-03-05 00:39:40.448 Reports[7123:967179] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7f81b04c6b00) → Save Synchronously? 1
After that, it just freezes. No error is thrown but the saving operation doesn't get completed either.
I replaced the places where I use the property context with NSManagedObjectContext.MR_defaultContext()
and ran the app and the data got saved successfully.
Why can't I pass in an instance of MR_defaultContext()
through the initializer?
Upvotes: 1
Views: 370
Reputation: 24237
Your backtrace says it all, you are setting up too many connections to the persistent store. The MagicalRecord documentation details that you should set up your stack either in the App Delegate's didFinishLaunching
phase, or in your case, when your DatabaseManager class is instantiated.
So the call to MagicalRecord.setupCoreDataStackWithStoreNamed("Records")
should move to your initializer (possibly safer to place this inside a dispatch_once block to prevent it from being setup more than once)
init(context: NSManagedObjectContext) {
struct Static {
static var onceToken : dispatch_once_t = 0
}
dispatch_once(&(Static.onceToken)) {
MagicalRecord.setupCoreDataStackWithStoreNamed("Records")
}
self.context = context
}
As an aside, you only need to call cleanup when your app is closing, so perhaps in your App Delegate's willTerminate
All the best with MagicalRecord :)
Upvotes: 1