如何正确设置 Core Data Stack 到 iOS 和 Swift 中的第一个视图控制器?
Posted
技术标签:
【中文标题】如何正确设置 Core Data Stack 到 iOS 和 Swift 中的第一个视图控制器?【英文标题】:How to correctly set up Core Data Stack to the first view controller in iOS and Swift? 【发布时间】:2014-09-29 22:14:22 【问题描述】:我想在我的 ios 应用程序中使用 Core Data,它使用 UINavigationController
和故事板上的第一个视图控制器。然后我想将AppDelegate.h
中的NSManagedObjectContext
和NSPersistentStoreCoordinator
传递给UINavigationController
中的第一个视图控制器。于是我先写了如下代码(注意我也用UISplitViewController
):
var splitViewController = self.window!.rootViewController as UISplitViewController
var navigationController: UINavigationController!
if splitViewController.viewControllers.count == 2
navigationController = splitViewController.viewControllers[1] as UINavigationController
else
navigationController = splitViewController.viewControllers[0] as UINavigationController
var firstViewController = navigationController.topViewController
firstViewController.managedObjectContext = managedObjectContext
但是,编译器说UIViewController
没有managedObjectContext
这样的属性。但奇怪的是,当我尝试通过println(firstViewController)
记录它时,它说它是FirstViewController
的一个实例,而不是UIViewController
... 但无论如何,我通过向下转换将其更改为以下内容:
var firstViewController = navigationController.topViewController as FirstViewController
然而,随后构建工作正常,但它立即因错误:"Swift dynamic cast failed"
在运行时崩溃。
那么我怎样才能将NSManagedObjectContext
(和NSPersistentStoreCoordinator
)传递给第一个视图控制器?
我在我的 iOS (iPad) 应用程序中使用 Xcode 6.1 Beta 2 和 Swift。
【问题讨论】:
【参考方案1】:您可以查看 https://github.com/Alecrim/AlecrimCoreData 中如何使用 Core Data。看起来它是一个经过深思熟虑的 Swift 核心数据库。
【讨论】:
【参考方案2】:您应该为核心数据定义一个单独的类并将其用于核心数据内容。这是一个示例类:
class CoreDataHelper
// MARK: - Properties
private lazy var applicationDocumentsDirectory: NSURL =
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
return urls[urls.count - 1] as NSURL
()
lazy var managedObjectModel: NSManagedObjectModel? =
if let modelURL = NSBundle.mainBundle().URLForResource("YOUR_MODEL_NAME", withExtension: "momd")
return NSManagedObjectModel(contentsOfURL: modelURL)
else
println("Error: can't create managed object model")
return nil
()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? =
if let managedObjectModel = self.managedObjectModel
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("YOUR_MODEL_NAME.sqlite")
var error: NSError? = nil
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options, error: &error)
if let error = error
println("Error: Can't add persistent store type to persistent store coordinate")
return nil
else
return coordinator
else
println("Error: Can't create persistant store coordinator. Because managed object model is not valid.")
return nil
()
lazy var managedObjectContext: NSManagedObjectContext? =
if let coordinator = self.persistentStoreCoordinator
let managedObjectContext = NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
else
println("Error: Can't create managed object context. Persistent store coordinator is not valid")
return nil
()
【讨论】:
【参考方案3】:我刚刚在 Xcode 6.0 中创建了一个主从应用程序并选中了包含 CoreData 框。模板中的代码完全符合您的要求...
你的第一个代码块:
var firstViewController = navigationController.topViewController
firstViewController.managedObjectContext = managedObjectContext
不起作用,因为在编译时,topViewController 是一个 UIViewController,即使它在运行时更具体。这就是你需要演员阵容的原因。
至于为什么你的沮丧不工作......要么navigationController
是空的,要么它的topViewController
是空的。前者比后者更有可能。
尝试将最后几行包裹在一些 if let
s 中,看看会发生什么:
if let nav = navigationController
if let firstViewController = navigationController.topViewController as? FirstViewController
firstViewController.managedObjectContext = managedObjectContext
else
println("navigationController.topViewController is not a FirstViewController")
else
println("navigationController is empty")
【讨论】:
navigationController
和 topViewController
都不为空,但它返回了 navigationController.topViewController is not a FirstViewController
。所以它未能将topViewController
向下转换为FirstViewController
,但我不知道为什么。以上是关于如何正确设置 Core Data Stack 到 iOS 和 Swift 中的第一个视图控制器?的主要内容,如果未能解决你的问题,请参考以下文章
CoreData学习:Core Data Stack(Swift)
ios 如何正确使用 NSPredicate 来匹配 Core Data 的 NSString?