【问题标题】:Swift - Using Core Data With CocoaSwift - 将核心数据与 Cocoa 一起使用
【发布时间】:2016-07-30 09:53:35
【问题描述】:

我正在为 OS X 应用程序使用Core Data。语言是SwiftCocoa 的工作方式有些奇怪。以下是 Xcode 创建的较短版本。

class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }

    // MARK: - Core Data stack
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. (The directory for the store is created, if necessary.) This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
        let fileManager = NSFileManager.defaultManager()
        var failError: NSError? = nil
        var shouldFail = false
        var failureReason = "There was an error creating or loading the application's saved data."

        // Make sure the application files directory is there
        do {
            let properties = try self.applicationDocumentsDirectory.resourceValuesForKeys([NSURLIsDirectoryKey])
            if !properties[NSURLIsDirectoryKey]!.boolValue {
                failureReason = "Expected a folder to store application data, found a file \(self.applicationDocumentsDirectory.path)."
                shouldFail = true
            }
        } catch  {
            let nserror = error as NSError
            if nserror.code == NSFileReadNoSuchFileError {
                do {
                    try fileManager.createDirectoryAtPath(self.applicationDocumentsDirectory.path!, withIntermediateDirectories: true, attributes: nil)
                } catch {
                    failError = nserror
                }
            } else {
                failError = nserror
            }
        }
    }()
}

在我向实体添加新记录后,找不到 Core Data 的 SQLite 文件。上面的代码中没有指向 SQLite 文件的指针。以下是iOS对应。

class AppDelegate: UIResponder, UIApplicationDelegate {
    // MARK: - Core Data stack
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
        // Create the coordinator and store
        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
        var failureReason = "There was an error creating or loading the application's saved data."
        do {
            try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
        } catch {
            // Report any error we got.
            var dict = [String: AnyObject]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
            dict[NSLocalizedFailureReasonErrorKey] = failureReason

            dict[NSUnderlyingErrorKey] = error as NSError
            let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
            // Replace this with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
            abort()
        }

        return coordinator
    }()
}

上面的代码指向一个 SQLite 文件。所以我在向实体插入记录时没有问题。

我正在使用 Xcode 7.2.1 我做错了吗?或者这是一个 Xcode 错误?

【问题讨论】:

  • 您到底想做什么,这给您带来了麻烦。上面的代码看起来像 Xcode 放入的自动生成的应用程序委托内容。您尝试添加记录的代码在哪里?
  • 如果您说您需要一个指向 SQLite 文件的指针,因为您要直接编辑数据库,那么您从根本上误解了 Core Data 的工作原理以及您应该如何使用它。您能否进一步解释您的代码预期会发生什么,以及您实际观察到什么?
  • 为什么不使用 Xcode 为您创建的代码?
  • @vadian 我说过这是 Xcode 创建的更短的版本。
  • @Duncan Babbage 我尝试以与 iOS 相同的方式将记录插入到实体中。但应用程序不会创建数据库文件。所以我检查了 Xcode 在 AppDelegate.swift 中生成的代码,与 iOS AppDelegate.swift 相比,它不包含 SQLite 的路径。

标签: swift macos cocoa core-data


【解决方案1】:

Swift 3 版本的@DuncanBabbage 解决方案:

class DataController: NSObject {
    var managedObjectContext: NSManagedObjectContext
    override init() {
        // This resource is the same name as your xcdatamodeld contained in your project.
        guard let modelURL = Bundle.main.url(forResource: "DataModel", withExtension:"momd") else {
            fatalError("Error loading model from bundle")
        }
        // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
        guard let mom = NSManagedObjectModel(contentsOf: modelURL) else {
            fatalError("Error initializing mom from: \(modelURL)")
        }
        let psc = NSPersistentStoreCoordinator(managedObjectModel: mom)
        managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = psc

        DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async {
            let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
            let docURL = urls[urls.endIndex-1]
            /* The directory the application uses to store the Core Data store file.
             This code uses a file named "DataModel.sqlite" in the application's documents directory.
             */
            let storeURL = docURL.appendingPathComponent("DataModel.sqlite")
            do {
                try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)
            } catch {
                fatalError("Error migrating store: \(error)")
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    您在此处发布的代码只是功能核心数据堆栈的一部分,不足以初始化核心数据。

    这是 Apple 当前用于初始化核心数据堆栈的示例代码:

    import CoreData
    class DataController: NSObject {
        var managedObjectContext: NSManagedObjectContext
        init() {
            // This resource is the same name as your xcdatamodeld contained in your project.
            guard let modelURL = NSBundle.mainBundle().URLForResource("DataModel", withExtension:"momd") else {
                fatalError("Error loading model from bundle")
            }
            // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
            guard let mom = NSManagedObjectModel(contentsOfURL: modelURL) else {
                fatalError("Error initializing mom from: \(modelURL)")
            }
            let psc = NSPersistentStoreCoordinator(managedObjectModel: mom)
            managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
            managedObjectContext.persistentStoreCoordinator = psc
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
                let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
                let docURL = urls[urls.endIndex-1]
                /* The directory the application uses to store the Core Data store file.
                 This code uses a file named "DataModel.sqlite" in the application's documents directory.
                 */
                let storeURL = docURL.URLByAppendingPathComponent("DataModel.sqlite")
                do {
                    try psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil)
                } catch {
                    fatalError("Error migrating store: \(error)")
                }
            }
        }
    }
    

    请参阅 Apple 的 Initialising the Core Data Stack

    【讨论】:

    • 好的。谢谢。所以它确实包含 SQLite 文件路径。为什么我不明白,你知道吗?你的 Xcode 版本是多少?
    最近更新 更多