gpt4 book ai didi

ios - 核心数据迁移后主 TableView 崩溃 Swift

转载 作者:行者123 更新时间:2023-11-28 21:41:53 25 4
gpt4 key购买 nike

我有一个相当标准的核心数据馈送 tableView,其中单元格数据从 fetchedResultsController 填充。

在我执行核心数据迁移之前,一切都按预期工作。轻量级迁移的目的是提供一个简单备份不要更改模型。该商店使用 SQLite。计划是进行迁移以生成新的数据文件,然后删除新存储并安装原始存储以保留原始文件名。

备份过程的 View 也是一个tableView。迁移完成后,新文件可见在备份 TableView 中。单击“返回”按钮返回到原始tableView后,数据为按预期可见,但单击 tableView 中的任何行会导致立即崩溃,我会看到可怕的“无法从此 NSManagedObjectContext 的协调器访问对象的持久存储”错误。

我已经为此苦苦挣扎了一个星期。我一定是错过了一个基本概念。任何帮助,将不胜感激。 (iOS 8, Xcode 6.4)

这里是 fetchedResultsController 变量。同样,这些工作一直有效,直到进行迁移:

var myFetchedResultsController: NSFetchedResultsController? = nil

var fetchedResultsController: NSFetchedResultsController {

managedObjectContext = kAppDelegate.managedObjectContext

if myFetchedResultsController != nil {
return myFetchedResultsController!
}//if my ! nil

let fetchRequest = NSFetchRequest()

let entity = NSEntityDescription.entityForName("Patient", inManagedObjectContext: managedObjectContext)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 50

//Sort keys
let sortDescriptor = NSSortDescriptor(key: "dateEntered", ascending: false)
let sortDescriptors = [sortDescriptor]

fetchRequest.sortDescriptors = [sortDescriptor]

let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

var countError : NSError? = nil
var count = managedObjectContext.countForFetchRequest(fetchRequest, error: &countError)

println("The count is \(count)")
//after creating a backup, this count is ALWAYS zero - never the real count

aFetchedResultsController.delegate = self
myFetchedResultsController = aFetchedResultsController

var error: NSError? = nil
if !myFetchedResultsController!.performFetch(&error) {
// Don't forget the code to handle the error appropriately.
println("Unresolved error \(error), \(error!.userInfo)")
//Remove this
abort()
}//if !my

return myFetchedResultsController!
}//var fetchedResultsController

备份程序的两个函数:

func createLocalBackupFile() {

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyyMMddHHmmss"
let theDateTime = NSDate()
let formattedDateTime = dateFormatter.stringFromDate(theDateTime)
let backupFileName : String = "BiopBak" + formattedDateTime + ".sqlite"
println("backupFileName is \(backupFileName)")

let psu : CRSPersistentStoreUtilities = CRSPersistentStoreUtilities()//the function below is in this class

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
//println("In a background queue, creating the backup file")
psu.backupTheStore(backupFileName)

//go back to the main queue
dispatch_async(dispatch_get_main_queue(), { () -> Void in
println("Back on main queue after creating the backup file")

if (self.backupSqlFiles.count == 1 && self.backupSqlFiles[0] == "Placeholder for empty list") {
self.backupSqlFiles.append(backupFileName.stringByDeletingPathExtension)
self.backupSqlFiles.removeAtIndex(0)

} else {
self.backupSqlFiles.append(backupFileName.stringByDeletingPathExtension)

}//if placeholder is only record in database - else

self.tableView.reloadData()
println("backupSqlFiles[] = \(self.backupSqlFiles)")

})//back to main block - inner
})//background processing block - outer

}//createLocalBackupFile

func backupTheStore(newSQLFileName : String) -> NSPersistentStore? {

let storeType = NSSQLiteStoreType
var migrateError : NSError?
var currentStore : NSPersistentStore = kAppDelegate.persistentStoreCoordinator?.persistentStores.last! as! NSPersistentStore
let options = [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true]

let fileManager = NSFileManager.defaultManager()
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docsDir = paths[0] as! String
let docsDirURL = NSURL(fileURLWithPath: docsDir)

let originalStoreURL : NSURL = docsDirURL?.URLByAppendingPathComponent("BiopLogCloud.sqlite") as NSURL!
var newStoreURL : NSURL = docsDirURL?.URLByAppendingPathComponent(newSQLFileName) as NSURL!

kAppDelegate.persistentStoreCoordinator?.migratePersistentStore(currentStore, toURL: newStoreURL, options: options, withType: storeType, error: &migrateError)

currentStore = kAppDelegate.persistentStoreCoordinator?.persistentStores.last! as! NSPersistentStore

var removeStoreError : NSError?
var theStores = kAppDelegate.persistentStoreCoordinator?.persistentStores

if let theStores2 = theStores {
for removeStore in theStores2 {
var removed : Bool = true
kAppDelegate.persistentStoreCoordinator?.removePersistentStore(removeStore as! NSPersistentStore, error: &removeStoreError)

if (removeStoreError != nil) {
println("Unable to remove persistent store \(removeStore)")
}
}//for in
}//if let theStores

var addStoreError : NSError?

kAppDelegate.persistentStoreCoordinator?.addPersistentStoreWithType(storeType,
configuration: nil,
URL: originalStoreURL,
options: options,
error:&addStoreError)

if (addStoreError != nil) {
println("Unable to add persistent store \(originalStoreURL)")
//change this to add a user alert
}//if

//this does not seem to do any good
let ptvc : PatientTableViewController = PatientTableViewController()

dispatch_async(dispatch_get_main_queue()) {
() -> Void in
ptvc.tableView.reloadData()
}//block

return thisStore

}//backupTheStore

最佳答案

似乎正在发生的事情是:

  1. 您正在 TableView 中显示一些托管对象,这些对象是在 migratePersistentStore 调用之前获取的。
  2. 您执行 migratePersistentStore 调用。您的 backupTheStore 方法将隐式删除原始持久存储(作为迁移调用的一部分),但它会尝试通过删除新的持久存储并重新添加旧的来修复问题。
  3. 然后您尝试使用第 1 步中的一个托管对象。

我认为,问题是尽管您重新添加了用于获取那些托管对象的持久存储,但是您的迁移过程已经失去了从托管对象到存储的连接。迁移调用清除持久存储协调器状态,这会中断托管对象/持久存储连接,并且添加持久存储不会重新创建该连接。 (也许它应该但显然不是它的设计方式)。

因此,您管理的对象无法与持久存储协调器关联到持久存储文件,并且当您尝试使用它们时会崩溃。

重新加载 TableView 是不够的,因为它只会从获取的结果 Controller 重新加载相同的托管对象。您还应该确保在获取的结果 Controller 上调用 performFetch 以使其重新获取其数据。如果这还不够,将 myFetchedResultsController 设置为 nil 并然后重新加载表,这样您将获得全新的提取。

关于ios - 核心数据迁移后主 TableView 崩溃 Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31754094/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com