Swift CoreData背景NSManagedObject故障

时间:2015-08-30 15:39:48

标签: ios swift core-data

我有以下问题:

我创建了一个NSManagedObject

func createRecord(participation: Participation, start: NSDate, course: Course?) -> Record {

    let newRecord = NSEntityDescription.insertNewObjectForEntityForName("Record", inManagedObjectContext: bmoc) as! Record

    newRecord.setValue(participation, forKey: "participation");
    newRecord.setValue(start, forKey: "start");
    newRecord.setValue(course, forKey: "course");
    newRecord.setValue(0, forKey: "finished");
    newRecord.setValue(0, forKey: "experience");
    newRecord.setValue(false, forKey: "synced");

    var err : NSError?
    bmoc.save(&err)
    if(err != nil) {
        NSLog(err!.description)
    }

    return newRecord;

然后我在具有调用此

的NSTimer的控制器中使用此对象
println(record!.start); labelTimer.setTime(NSDate().timeIntervalSinceDate(record!.start))   

Controller定义了这两种方法来启动和停止计时器。在AppDelegate中,这些方法被调用并按预期工作。

func applicationWillResignActive(application: UIApplication) {
    println("applicationWillResignActive")
    trackingDelegate?.stopTimer()
}

func applicationDidBecomeActive(application: UIApplication) {
    println("applicationDidBecomeActive")
    trackingDelegate?.startTimer()
}

基本思想是让用户以一个调用startTimer()的按钮启动计时器。当用户使用主页按钮关闭应用程序时,将调用StopTimer()并且没有任何问题。当应用程序确实成为活跃时,我在println(record!.start)

时收到以下错误
THREAD 1: EXC_BAD_ACCESS (code=1, address = 0x0)

有谁知道为什么? Object是持久的。如果我使用sqlite-viewer检查数据库,我会看到它..当我尝试访问其他两个对象参与并在控制器中直接使用类似course.name之类的东西时,它工作,record.course.name没有。只有Record-Object似乎有问题。

Record-Object的运行时值:

Printing description of self.record:
(StudyTracker.Record?) record = 0x00007ff7a2ee3ea0 {
  CoreData.NSManagedObject = {
    NSManagedObject = {
      NSObject = {
        isa = StudyTracker.Record_Record_
      }
      _cd_rc = 4
      _cd_stateFlags = 40667072
      _cd_rawData = nil
      _cd_entity = 0x00007ff7a2e74dd0
      _cd_managedObjectContext = 0x00007ff7a2d2fbb0
      _cd_objectID = 0xd00000000158000a
      _cd_extraFlags = 104
      _cd_observationInfo = nil
      _cd_snapshots = 0x0000000000000000
      _cd_lockingInfo = 0
      _cd_queueReference = 0x00007ff7a2d4a490
    }
  }
}

CoreData的代码是默认代码:

lazy var applicationDocumentsDirectory: NSURL = {
    // The directory the application uses to store the Core Data store file. This code uses a directory named "de.unikassel.StudyTracker" in the application's documents Application Support directory.
    let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
    return urls[urls.count-1] as! NSURL
    }()

lazy var managedObjectModel: NSManagedObjectModel = {
    // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
    let modelURL = NSBundle.mainBundle().URLForResource("StudyTracker", withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
    }()

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
    // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
    // Create the coordinator and store
    var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("StudyTracker.sqlite")
    var error: NSError? = nil
    var failureReason = "There was an error creating or loading the application's saved data."
    if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil {
        coordinator = nil
        // Report any error we got.
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
        dict[NSLocalizedFailureReasonErrorKey] = failureReason
        dict[NSUnderlyingErrorKey] = error
        error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
        // Replace this 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.
        NSLog("Unresolved error \(error), \(error!.userInfo)")
        abort()
    }

    return coordinator
    }()

lazy var managedObjectContext: NSManagedObjectContext? = {
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
    let coordinator = self.persistentStoreCoordinator
    if coordinator == nil {
        return nil
    }
    var managedObjectContext = NSManagedObjectContext()
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext
    }()

提前致以最诚挚的问候和谢意, 基督教

2 个答案:

答案 0 :(得分:1)

在设置coredata时,基本上将此上下文与concurrencyType MainQueueConcurrencyType一起使用也是一个技巧,特别是在以后使用wiget时。

a

Duncan的建议有效,但由于与小部件共享数据而不得不改变上下文类型,因此在某种程度上是多余的。

感谢您的帮助!

答案 1 :(得分:0)

计时器将在与用于创建managedObject的线程不同的线程上调用代码,因此您需要确保从同一个线程调用println(!record.start),这可能是主线程。像这样:

NSOperationQueue.mainQueue().addOperationWithBlock {
                    println(!record.start)
                }

dispatch_async(dispatch_get_main_queue(), {
                println(!record.start)
            })