简体   繁体   English

如何在核心数据Swift 3中使用persistentStore(for:url)

[英]How to use persistentStore(for: url) in core data Swift 3

I'm trying to do the following: 我正在尝试执行以下操作:

Tap a cell of a UITableView cell then segue to the next UIViewController and display the database results. 轻按的小区UITableView细胞然后segue到下一个UIViewController和显示数据库的结果。 But there are multiple persistent stores therefore the designated store is specified by the cell label text. 但是有多个持久性存储,因此指定的存储由单元标签文本指定。

The question is: How to use the method persistentStore(for: url) ? 问题是:如何使用方法persistentStore(for: url) Or is there some else way to specify a persistent store for the fetchRequest ? 还是有其他方法为fetchRequest指定持久存储?

Here is my code that is not working: 这是我的代码不起作用:

func wordFetchRequest() -> NSFetchRequest<Word> {
    let fr = NSFetchRequest<Word>(entityName: "Word")
    fr.fetchBatchSize = 100

    // Assigning sort descriptors
    let firstLetterSort = NSSortDescriptor(key: #keyPath(Word.firstLetter), ascending: true)
    let spellSort = NSSortDescriptor(key: #keyPath(Word.spell), ascending: true)
    fr.sortDescriptors = [firstLetterSort, spellSort]

    // Get URL of the designated store to fetch
    let libname = (AppDelegate.nameDict as NSDictionary).allKeys(for: nameToFetch).first!

// I'm not sure the following line: which file should I use? I've tried
//.sqlite, .sqlite-shm and .sqlite-wal but none worked.
    let url = AppDelegate.coreDataStack.storeDirectory.appendingPathComponent("\(libname).sqlite-wal")

    // Specify affected store for the fetch request
    var pss = [NSPersistentStore]()
    print(url)

// The following line fails:
    if let ps = coreDataStack.psc.persistentStore(for: url) {
        pss.append(ps)
    } else {

    }

    fr.affectedStores = pss
    print(fr.affectedStores ?? "No stores available.")
    return fr
}

Any help will be much appreciated. 任何帮助都感激不尽。

I had to deal with similar scenario where I had different persistent stores (to be specific one of type NSInMemoryStoreType and other of type NSSQLiteStoreType to be specific) 我不得不处理类似的情况,即我拥有不同的持久性存储(具体来说,一种类型为NSInMemoryStoreType,而另一种类型为NSSQLiteStoreType

I found it easier to create separate persistent store coordinators for each store and create separate managed object context using these persistent stores as there parent stores :) 我发现为每个商店创建单独的持久性存储协调器和使用这些持久性存储(如父存储)创建单独的管理对象上下文更容易:

Here is the code which was written in iOS 9 swift 3, hence has older core data stack operations, I have seen iOS 10 Swift 3 Core data stack, I believe these methods can still give you idea of what am talking here :) 这是用iOS 9 swift 3编写的代码,因此具有较旧的核心数据堆栈操作,我已经看到了iOS 10 Swift 3 Core数据堆栈,我相信这些方法仍然可以使您了解这里所说的内容:)

This is what you will see by default in Coredata stack, getter for persistentStoreCoordinator 这就是你将默认在Coredata堆栈看到,getter方法persistentStoreCoordinator

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.appendingPathComponent("SingleViewCoreData.sqlite")
        var failureReason = "There was an error creating or loading the application's saved data."
        do {
            try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
            log.debug(url)
        } catch let error as NSError {
            // Report any error we got.
            var dict = [String: AnyObject]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
            dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?

            dict[NSUnderlyingErrorKey] = error
            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()
        }
        catch{

        }
        return coordinator
    }()

Important statement here though is 重要的声明是

try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)

As you can see it specifies the persistent store type as Sqlite and specifies the configurationName as nil, which means default configuration :) 如您所见,它将持久性存储类型指定为Sqlite并将configurationName指定为nil,这意味着默认配置:)

You can create multiple configurations in Coredata and specify there name in this statement to create separate persistent store coordinator for each configurations :) 您可以在Coredata中创建多个配置,并在此语句中指定名称,以便为每个配置创建单独的持久性存储协调器:)

You can have a look at my blog Can core data be trusted with sensitive informations to see how you can create multiple configurations and stores :) 您可以在我的博客中查看是否可以使用敏感信息信任核心数据,以了解如何创建多个配置和存储:)

So lets assume you create another configuration and added entities to them and lets call it as "Test1" configuration, you will create a separate persistent store coordinator for that using, 因此,假设您创建了另一个配置并向其中添加了实体,并将其称为“ Test1”配置,您将为此创建一个单独的持久性存储协调器,

lazy var test1PersistentStoreCoordinator: 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.appendingPathComponent("SingleViewCoreData.sqlite")
    var failureReason = "There was an error creating or loading the application's saved data."
    do {
        try coordinator.addPersistentStore(ofType: NSInMemoryStoreType, configurationName: "Test1", at: url, options: nil)
        log.debug(url)
    } catch let error as NSError {
        // Report any error we got.
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
        dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?

        dict[NSUnderlyingErrorKey] = error
        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()
    }
    catch{

    }
    return coordinator
}()

Now you have two persistent store coordinators associated with two different configurations, simply create two managed object contexts using these persistent store coordinators as their parent store :) 现在,您有两个与两种不同配置关联的持久性存储协调器,只需使用这些持久性存储协调器作为其父存储创建两个托管对象上下文:)

   lazy var managedObjectContext: NSManagedObjectContext = {
        // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
        let coordinator = self.persistentStoreCoordinator
        var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
    }()


    lazy var managedObjectContextForBackTracking : NSManagedObjectContext = {
        let coordinator = self.test1PersistentStoreCoordinator
        var managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
    }()

Thats it :) 而已 :)

Now run your fetch requests on corresponding managedObject contexts :) and be sure that nothing messes up your core data :) 现在,在相应的ManagedObject上下文上运行获取请求:),确保没有混乱您的核心数据:)

Hope it helps :) 希望能帮助到你 :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM