在 AppDelegate 中为其他 Viewcontroller 初始化 managedContect
Posted
技术标签:
【中文标题】在 AppDelegate 中为其他 Viewcontroller 初始化 managedContect【英文标题】:Initialize managedContect in AppDelegate for other Viewcontroller 【发布时间】: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) " 谢谢! 【参考方案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
对于哪种设计模式更好,意见不一。
【讨论】:
以上是关于在 AppDelegate 中为其他 Viewcontroller 初始化 managedContect的主要内容,如果未能解决你的问题,请参考以下文章
在 AppDelegate 中为两个视图控制器使用和更新 NSMutableString
有没有办法在 appdelegate 中为整个项目的所有 UIImage 属性使用`UIImageRenderingModeAlwaysOriginal`
使用 Appdelegate 在 IOS Swift 中为所有视图控制器创建 Firebase CRUD 方法