来自 CoreDataStack 的托管上下文不会通过导航栏持续存在

Managed Context from CoreDataStack isn't persisting through the navigationbar

我正在尝试设置一个联系人页面,以便我可以 add/edit 联系。 但是,当我尝试调用我的 CoreDataStack.context.

时,我得到了一个零值

这里起源于AppDelegate

lazy var coreDataStack = CoreDataStack()


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    UINavigationBar.appearance().barTintColor = navigationMainColor
    UINavigationBar.appearance().tintColor = navigationMainItemColor

    let navigationController = window!.rootViewController as! UINavigationController
    let listViewController = navigationController.topViewController as! ViewController
    listViewController.coreDataStack = coreDataStack

    return true
}

我将它传递给我的第一个视图控制器,在 rootViewController 中,我有一个按钮可以将我发送到另一个视图控制器。在 rootViewController 中,当我调用 print(coreDataStack) 时,CoreDataStack 上下文仍然存在。所以我知道它存在于第一个视图中。我按下去联系人页面的按钮是工具栏上的一个条形按钮。

可能的问题 1 可能是我没有使用导航栏来回移动,但是所有视图都嵌入在导航堆栈中。

我是否需要在第一个视图控制器中准备 prepareForSegue 才能传递 NSManagedObjectContext?

联系人和新的联系人视图控制器之间还有一个导航控制器。但是 nil 似乎在那之前就被退回了。 在联系人视图控制器中,可以在此处找到检查用户是否尝试添加联系人的 prepareForSegue

else if segue.identifier == "AddContact" {
        let navigationController = segue.destinationViewController as! UINavigationController
        let addViewController = navigationController.topViewController as! NewContactViewController
        let contactEntity = NSEntityDescription.entityForName("Contact", inManagedObjectContext: coreDataStack.context)

        let newContact = Contact(entity: contactEntity!, insertIntoManagedObjectContext: coreDataStack.context)

        addViewController.contact = newContact
        addViewController.context = newContact.managedObjectContext
        addViewController.delegate = self
    }

我得到的错误是 coreDataStack.context 当我尝试创建新联系人时返回 nil。我已经为此忙了几个小时,我想我错过了一些非常小或大的东西。无论哪种方式,我只想学习 Core Data 并变得更好。

你的核心数据栈应该是单例class对象。现在,如果您创建一个新的核心数据应用程序,Apple 会在 AppDelegate 中为您创建管道代码。由于 AppDelegate 是单例 class,您可以在应用程序的任何位置以 AppDelegate.coredatastack 访问核心数据栈。 由于您还在 Appdelegate 中定义了 coredatastack,因此您不必在视图控制器中传递它,可以使用

直接访问它
let delegate = UIApplication.sharedApplication().delegate as AppDelegate 
delegate.coredatastack

Do I need to prepareForSegue inside the first view controller in order to pass the NSManagedObjectContext?

是的,这正是您遇到的问题。您需要自己进行依赖注入,因为 Apple 无法预测您想要的东西:)

如果您的传入(目标)视图控制器包含在导航控制器中,您可以安全地假设那一点 topViewController 是您的视图控制器(并且您可以测试这个)并注入它。

So simply get the navigation controller and then get the destination controller? Is it simply a matter of destinationcontroller.context = self.context in the prepareforsegue for the first view controller?

反过来:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    guard let destinationNavController = segue.destinationViewController as? UINavigationController else {
        print("Unexpected view controller: \(seque.destinationViewController.self)")
    }
    guard let myViewController = destinationNavController.topViewController as? MyViewController else {
        print("Unexpected view controller: \(destinationNavController.topViewController.self)")
    }
    myViewController.context = context
}

根据需要用您的 class 名字替换片段。

Yeah I figured, now I'm getting an odd error that I can't force downcast my ContactViewController to UINavigationController. Is it possible that my ContactViewController isn't on the navigation stack?

好吧,退后一步。如果您只是在导航堆栈中弹出视图控制器,那么您将 ContactViewController 直接作为目的地,您可以像这样跳过导航控制器:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    guard let myViewController = segue.destinationViewController as? MyViewController else {
        print("Unexpected view controller: \(destinationNavController.topViewController.self)")
    }
    myViewController.context = context
}

如果 segue 指向一个 NEW UINavigationController 那么还有其他问题。