我想在我的iOS应用中使用Core Data,它使用UINavigationController
和故事板上的第一个视图控制器。然后我想将NSManagedObjectContext
中的NSPersistentStoreCoordinator
和AppDelegate.h
传递给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。
答案 0 :(得分:2)
您可以查看https://github.com/Alecrim/AlecrimCoreData中核心数据的使用方式。它看起来好像是一个经过深思熟虑的Swift核心数据库。
答案 1 :(得分:1)
您应该为Core Data定义一个单独的类,并将其用于核心数据。这是一个示例类:
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
}
}()
}
答案 2 :(得分:1)
我刚刚在Xcode 6.0中创建了一个Master-Detail应用程序,并检查了包含CoreData框。模板中的代码完全符合您的要求......
您的第一段代码:
var firstViewController = navigationController.topViewController
firstViewController.managedObjectContext = managedObjectContext
不能正常工作,因为在编译时,topViewController是一个UIViewController,即使它在运行时更具体。这就是你需要演员的原因。
至于为什么你的堕落者没有工作...... navigationController
为空,或者topViewController
为空。前者比后者更可能。
尝试将最后几行包裹在某些if let
中,看看会发生什么:
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")
}