在 iOS 中正确访问 ViewController 中的核心数据上下文 [重复]

Posted

技术标签:

【中文标题】在 iOS 中正确访问 ViewController 中的核心数据上下文 [重复]【英文标题】:accessing Core Data context in ViewController properly in iOS [duplicate] 【发布时间】:2016-08-30 19:18:03 【问题描述】:

我一直在做

let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

只在我的 ViewControllers 中使用上下文,但在我阅读的 Apples ios 开发人员库中

“视图控制器通常不应该从全局对象(例如应用程序委托)中检索上下文”

那么从 AppDelegate 访问上下文的正确方法是什么,我有点困惑...

【问题讨论】:

@Wain 重复的问题没有带有代码的示例解决方案。那该怎么办,我应该把我的答案移到那里吗? 你可以,当我将其标记为重复时,你的答案是一个简单的链接,但是这个问题/答案没有意义,因为它是相同的,而且它的理论很重要 - 添加在很多情况下,代码只是让人们不假思索地复制和粘贴 【参考方案1】:

您是对的,Apple 不建议 iOS 应用程序采用这种方式。

创建CoreData堆栈是最好的解决方案:

所以在你的 AppDelegate.swift 中:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate 

  var window: UIWindow?
  lazy var coreDataStack = CoreDataStack()

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

    let navigationController =
self.window!.rootViewController as! UINavigationController

    let viewController =
navigationController.topViewController as! ViewController

    viewController.managedContext = coreDataStack.context

    return true
  

  func applicationDidEnterBackground(_ application: UIApplication) 
    coreDataStack.saveContext()
  

  func applicationWillTerminate(_ application: UIApplication) 
    coreDataStack.saveContext()
  

然后,一个 CoreDataStack.swift(负责 MOC 的所有职责的类)的示例:

import CoreData    
class CoreDataStack 

  lazy var context: NSManagedObjectContext = 

    var managedObjectContext = NSManagedObjectContext(
      concurrencyType: .mainQueueConcurrencyType)

    managedObjectContext.persistentStoreCoordinator = self.psc
    return managedObjectContext
    ()

  fileprivate lazy var psc: NSPersistentStoreCoordinator = 

    let coordinator = NSPersistentStoreCoordinator(
      managedObjectModel: self.managedObjectModel)

    let url = self.applicationDocumentsDirectory
      .appendingPathComponent(self.modelName)

    do 
      let options =
      [NSMigratePersistentStoresAutomaticallyOption : true]

      try coordinator.addPersistentStore(
        ofType: NSSQLiteStoreType, configurationName: nil, at: url,
        options: options)
     catch  
      print("Error adding persistent store.")
    

    return coordinator
    ()

  fileprivate lazy var managedObjectModel: NSManagedObjectModel = 

    let modelURL = Bundle.main
      .url(forResource: self.modelName,
        withExtension: "momd")!
    return NSManagedObjectModel(contentsOf: modelURL)!
    ()

  fileprivate lazy var applicationDocumentsDirectory: URL = 
    let urls = FileManager.default.urls(
      for: .documentDirectory, in: .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()
      
    
  

最后是 ViewController.swift 的示例:

import CoreData    
class ViewController: UIViewController 

  var managedContext: NSManagedObjectContext!      
  override func viewDidLoad()         

    let myEntity = NSEntityDescription.entity(forEntityName: "MyEntityName",
      in: managedContext)

    ...

  


【讨论】:

等等...所以,我不应该使用 xcode 自动生成的核心数据堆栈吗?这与有何不同 是的,正如引用的“理想情况下,每个视图控制器都应该是一个独立的岛屿。它不应依赖于其父级,也不应依赖于 Application Delegate。一旦视图控制器被推到屏幕上,理想情况下它应该是它自己的主人。他们的文档有点乱。这里有更多信息:cimgf.com/2011/01/07/… 感谢链接和示例代码,非常有帮助 我的回答对你有帮助吗? :) 是的,非常有帮助。谢谢你。但是在更改之后,我决定改回原来的方法。原因是 1. 我没有重用我的代码。 2. 我的项目很简单,以“正确”的方式进行实际上会使事情复杂化一点。

以上是关于在 iOS 中正确访问 ViewController 中的核心数据上下文 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

材料设计的ButtomSheet没有正确显示 - 快速

在 ViewControllers 之间共享信息 [重复]

如何从另一个 UIView 类访问 UIControl 的值

ios NSKeyedArchiver 释放 = 错误访问

有没有办法在Swift中以编程方式设置NSCollectionView?

iOS:“.03 小时”文本的旁白不正确