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

时间:2016-11-28 07:57:07

标签: ios swift xcode core-data

我试图执行以下操作:

点击UITableView单元格的单元格,然后点击segue到下一个UIViewController,并显示数据库结果。但是有多个持久存储因此指定的存储由单元格标签文本指定。

问题是:如何使用方法persistentStore(for: url)?或者是否有其他方法为fetchRequest指定持久性存储?

这是我的代码无效:

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
}

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我必须处理类似的情况,我有不同的持久存储(具体类型为 NSInMemoryStoreType ,其他类型 NSSQLiteStoreType 是特定的)

我发现为每个商店创建单独的持久性商店协调员更容易,并使用这些持久性商店创建单独的托管对象上下文,因为父商店:)

这是用iOS 9 swift 3编写的代码,因此具有较旧的核心数据堆栈操作,我见过iOS 10 Swift 3 Core数据堆栈,我相信这些方法仍然可以让你了解这里的内容: )

默认情况下,您将在Coredata堆栈中看到这一点,对于 persistentStoreCoordinator

getter
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
    }()

这里的重要声明是

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

如您所见,它将持久存储类型指定为Sqlite,并将configurationName指定为nil,这意味着默认配置:)

您可以在Coredata中创建多个配置,并在此语句中指定名称,以便为每个配置创建单独的持久性存储协调器:)

您可以查看我的博客Can core data be trusted with sensitive informations,了解如何创建多个配置和商店:)

因此,假设您创建了另一个配置并向其添加了实体,并将其称为&#34; Test1&#34;配置,您将使用

为其创建一个单独的持久性存储协调器
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
}()

现在,您有两个与两个不同配置关联的持久性存储协调器,只需使用这些持久性存储协调器作为其父存储创建两个托管对象上下文:)

   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
    }()

多数民众赞成:)

现在在相应的managedObject上下文中运行你的获取请求:)并确保没有任何东西弄乱你的核心数据:)

希望有所帮助:)