使用可选的 managedObject 查找 nil,使用 CoreData 和 NSFetchedResultsCon



我正在尝试用一些CoreData填充集合视图。我正在用 Swift 编程,使用的是 iOS 9。我几乎都正确连接了(据我所知),但由于一行代码,我一直遇到崩溃。

这是来自我的视图控制器的代码。错误为 nil 的行是"managedObjectContext: coreDataStack.context":

override func viewDidLoad() {
    super.viewDidLoad()
    //1
    let fetchRequest = NSFetchRequest(entityName: "Family")
    let firstNameSort =
    NSSortDescriptor(key: "firstName", ascending: true)
    fetchRequest.sortDescriptors = [firstNameSort]
    //2
    fetchedResultsController =
        NSFetchedResultsController(fetchRequest: fetchRequest,
            managedObjectContext: coreDataStack.context,
            sectionNameKeyPath: nil,
            cacheName: nil)
    fetchedResultsController.delegate = CollectionViewFetchedResultsControllerDelegate(collectionView: familyCollectionView)
    //3
    do {
        try fetchedResultsController.performFetch()
    } catch let error as NSError {
        print("Error: (error.localizedDescription)")
    }
}

下面是我引用的"CoreDataStack"对象:

import Foundation
import CoreData
class CoreDataStack {
let modelName = "CoreDataModel"
lazy var context: NSManagedObjectContext = {
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = self.psc
    return managedObjectContext
}()
private lazy var psc: NSPersistentStoreCoordinator = {
    let coordinator = NSPersistentStoreCoordinator(
        managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory
        .URLByAppendingPathComponent(self.modelName)
    do {
        let options =
        [NSMigratePersistentStoresAutomaticallyOption : true]
        try coordinator.addPersistentStoreWithType(
            NSSQLiteStoreType, configuration: nil, URL: url,
            options: options)
    } catch  {
                print("Error adding persistent store.")
    }
    return coordinator
}()
private lazy var managedObjectModel: NSManagedObjectModel = {
    let modelURL = NSBundle.mainBundle()
        .URLForResource(self.modelName,
        withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
private lazy var applicationDocumentsDirectory: NSURL = {
    let urls = NSFileManager.defaultManager().URLsForDirectory(
    .DocumentDirectory, inDomains: .UserDomainMask)
    return urls[urls.count-1]
}()
func saveContext () {
    if context.hasChanges {
    do {
        try context.save()
    } catch let error as NSError {
            print("Error: (error.localizedDescription)")
            abort()
    }
    }
}

}

关于为什么当我打电话给那条线时我拿起 nil 的任何想法?

存在此问题是因为从未分配过self.coreDataStack,但是在定义fetchedResultsController时访问了它。

要简单地解决问题,请在访问视图控制器的 coreDataStack 属性之前创建 CoreDataStuck 并将其作为实例分配给该属性:

self.coreDataStack = CoreDataStack()

我想强调的是管理NSManagedObjectContext的重要性。我相信创建 CoreDataStack 的实例并在需要时传递对它的引用是一种更常见的模式。例如,您可以在应用程序委托中创建它的实例,并使用如下所示的方式将引用分配给您的第一个视图控制器:

lazy var cds = CoreDataStack()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSOBject: AnyObject?]?) -> Bool {
// Obtain a reference to your root view controller, this may have to be different if you use different types of controllers. This would be the View controller where you use the core data stack in your question though.
let vc = window!.rootViewController as! ViewController
vc.coreDataStack = self.cds // This will now ensure the property on your view controller is assigned and can be accessed.
return true
}

稍后在您的应用程序中,我建议传递相同的引用。您可以通过访问应用程序委托来做到这一点,我个人认为通过准备 segue 方法传递引用会更干净。我只是假设您的应用程序中存在一个 SecondViewController 类,并且您正在从问题中的 ViewController 过渡到它:

class SecondViewController: UIViewController {
    var cds: CoreDataStack!
}

我假设ViewController和SecondViewController之间有一个名为"next"的Segue。在 ViewController 文件中,定义 prepareForSegue 方法:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "next" {
        let secondVc = segue.destinationViewController as! SecondViewController
        secondVc.cds = self.coreDataStack 
    }
}

我试图强调保留对首次创建的核心数据堆栈实例的引用的想法,我认为随着您的发展,您会发现它更有益。

最新更新