【问题标题】:Initialize managedContect in AppDelegate for other Viewcontroller在 AppDelegate 中为其他 Viewcontroller 初始化 managedContect
【发布时间】:2017-12-11 08:58:53
【问题描述】:

我想初始化 managedObject,但总是报这个错:

线程 1:致命错误:打开包装时意外发现 nil 可选值

我想使用 Core Data / managedObject 的 ViewController 不是我启动的 ViewController,而是我正在通过启动 ViewController 访问的另一个 (PortfolioVC)。

这是我的代码:

import Foundation
import CoreData

class DatabaseController {
    private let modelName: String

    init(modelName: String) {
        self.modelName = modelName
    }

    lazy var managedContext: NSManagedObjectContext = {
        return self.storeContainer.viewContext
    }()

    private lazy var storeContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: self.modelName)
        container.loadPersistentStores { (storeDescription, error) in
            if let error = error as NSError? {
                print("Unresolved error \(error), \(error.userInfo)")
            }
        }
        return container
    }()

    func saveContext () {
        guard managedContext.hasChanges else { return }

        do {
            try managedContext.save()
        } catch let error as NSError {
            print("Unresolved error \(error), \(error.userInfo)")
        }
    }
}

这是我的 AppDelegate:

import UIKit
import CoreData

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    lazy var coreDataStack = DatabaseController(modelName: "Portfolio")

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        guard let navController = window?.rootViewController as? UINavigationController,
            let viewController = navController.topViewController as? PortfolioVC else {
                return true
        }
        viewController.managedContext = coreDataStack.managedContext
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {

    }

    func applicationDidEnterBackground(_ application: UIApplication) {

        coreDataStack.saveContext()
    }

    func applicationWillEnterForeground(_ application: UIApplication) {

    }

    func applicationDidBecomeActive(_ application: UIApplication) {

    }

    func applicationWillTerminate(_ application: UIApplication) {

        coreDataStack.saveContext()
    }


}

这是 PortfolioVC 中的代码:

导入 UIKit 导入核心数据

class PortfolioVC: UIViewController {


    var managedContext: NSManagedObjectContext!
    var namePortfolio: NamePortfolio?

override func viewDidLoad() {
        super.viewDidLoad()
        tableViewPortfolio.dataSource = self

        let standardPortfolio = "Watchlist"
        let fetchRequest: NSFetchRequest<NamePortfolio> = NamePortfolio.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "%K == %@", #keyPath(NamePortfolio.name), standardPortfolio)

        do {
            let results = try managedContext.fetch(fetchRequest) // here I get the error (managedContext = nil)
            if results.count > 0 {
                // Portfolio already created
                namePortfolio = results.first

            } else {
                // no Portfolio
                namePortfolio = NamePortfolio(context: managedContext)
                namePortfolio?.name = standardPortfolio
                try managedContext.save()
            }
        }  catch let error as NSError {

            print("Could not fetch \(error), \(error.userInfo)")
        }

    }

非常感谢您的帮助!

【问题讨论】:

  • 如何从“启动视图控制器”访问 PortfolioVC?
  • 使用这样的 UIButton:“@IBAction func portfolio(_ sender: Any) { performSegue(withIdentifier: "segueToPortfolio", sender: self) }" 谢谢!

标签: ios swift core-data nsmanagedobject


【解决方案1】:

didFinishLaunchingWithOptions 中的代码运行时,PortfolioVC 还没有被添加到导航控制器堆栈中(甚至还没有被实例化),所以守卫失败了。有两种方法可以将 managedContext 获取到 PortfolioVC:

a) 在 didFinishLaunchingWithOptions 中将其传递给您的启动视图控制器,然后使用 prepareForSegue 将其从那里传递给 PortfolioVC。您需要向启动的 VC 添加 managedContext 属性,即使您只需要将其传递给 Portfolio VC。

b) 在 PortfolioVC 中,获取对 AppDelegate 的引用,然后从那里获取 managedContext。

    if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
        managedContext = appDelegate.coreDataStack.managedContext
    }

对于哪种设计模式更好,意见不一。

【讨论】:

    猜你喜欢
    • 2017-05-19
    • 2016-12-21
    • 1970-01-01
    • 2021-09-25
    • 2013-06-28
    • 2017-02-01
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多