在将我的应用程序升级到Swift 3和iOS 10之前,我没有将CoreData用作简单对象的数据存储的问题。轻量级迁移非常简单,节省成本,提取简单等。但自从最近的升级以来,我一直在CoreData遇到麻烦。Swift 3/iOS 10,正确的核心数据使用
我的问题分两部分。首先,是否有人知道有哪些好的资源可以帮助我了解CoreData如何在幕后工作,以便我能够更好地进行调试? Apple的文档极其有限,我阅读的所有文章都像新的CoreData一样简单。我有关于关系数据库的体面经验,所以CoreData为我添加了一个不舒服的抽象层。
二,以下代码有什么问题?使用此代码轻量级迁移不像iOS 10之前那样工作。对象保存到CoreData(我可以在保存后在应用程序中与它们交互),但在应用程序重新启动后消失。
lazy var persistentContainer: NSPersistentContainer = {
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
let container = NSPersistentContainer(name: "MY_APP")
container.persistentStoreDescriptions = [description]
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions = [description]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext() {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
我使用一个单独的文件,以抽象我的对象存储:
class Repository
{
func getContext() -> NSManagedObjectContext
{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
func delete<T>(_ a: some T)
{
getContext().delete(a as! NSManagedObject)
}
// ----------- Password Repo ----------
func savePassword(name: String, hint: String, un: String) {
let context = getContext()
//retrieve the entity that we just created
let entity = NSEntityDescription.entity(forEntityName: "Password", in: context)
let transc = NSManagedObject(entity: entity!, insertInto: context)
//set the entity values
transc.setValue(name, forKey: "name")
transc.setValue(hint, forKey: "thing")
transc.setValue(un, forKey: "newThing")
//save the object
do {
try context.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
} catch {
}
}
func updatePassword(pas: Password) -> Password
{
let context = getContext()
// sec.is_new = false
// TODO, add updates
// Try updating the model in the DB
do {
try context.save()
} catch {
print(error)
}
return pas
}
func fetchPasswords() -> [Password]
{
let context = getContext()
//create a fetch request, telling it about the entity
let fetchRequest: NSFetchRequest<Password> = Password.fetchRequest() as! NSFetchRequest<Password>
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
//go get the results
let searchResults = try getContext().fetch(fetchRequest)
return searchResults
} catch {
print("Error with request: \(error)")
}
return []
}
// ----------- End Password Repo ----------
// ----------- Hints Repo ----------
func saveHint (name: String, hint: String) {
let context = getContext()
//retrieve the entity that we just created
let entity = NSEntityDescription.entity(forEntityName: "Hint", in: context)
let transc = NSManagedObject(entity: entity!, insertInto: context)
//set the entity values
transc.setValue(value1, forKey: "some_string")
transc.setValue(value2, forKey: "some_thing")
//save the object
do {
try context.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
} catch {
}
}
func fetchHints() -> [Hint]
{
let context = getContext()
//create a fetch request, telling it about the entity
let fetchRequest: NSFetchRequest<Hint> = Hint.fetchRequest() as! NSFetchRequest<Hint>
let sortDescriptor = NSSortDescriptor(key: "my_key", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
//go get the results
let searchResults = try getContext().fetch(fetchRequest)
return searchResults
} catch {
print("Error with request: \(error)")
}
return []
}
}
然后我把这个资源库类,像这样:
Repository().savePassword(name: nameText.text!, hint: hintSoFarLabel.text!, un: "Hey")
repository类工作,直到我重新启动应用程序...
我也试图迁移到我的Core Da的新版本ta模型,它简单地添加了非可选的String属性(具有默认值),这将是iOS 9/Swift 2中的一个简单轻量级迁移。我错过了关于swift 3轻量级迁移的内容?
我毫不怀疑,问题是我没有足够好地理解iOS 10中的CoreData。我一直是一名软件工程师,但我只用iOS和Swift工作了几个月,所以请温和。并且预先感谢!
如果事情变得更简单,'NSPersistentContainer'不是Swift 3的东西,也不是必需的。您可以继续使用与iOS早期版本相同的类。他们仍然工作,不被弃用。而且,消失的物体与迁移无关。如果迁移现有的持久性存储失败,则该应用在启动时会崩溃。 –
@TomHarrington。谢谢,这是一个很好的建议,我会尝试一下。然而,这个特定的应用程序开始于Xcode 8,Swift 3和iOS 10目标。所以我想我应该坚持这些范例。我想弄清楚如何使用这样的应用程序进行简单的轻量级迁移。我在iOS 9之前编写了一个不同的应用程序,这就是我对iOS9迁移和iOS10的了解。 – Griffin
我正在研究一个简单的应用程序和新的Coredata(swift3),我注意到每个人我都设置ShouldInferMapping ...和ShouldMigrateStoreAu ...为true来描述,并将它们设置为container.persistenStoreDescriptions,正如Griffin指出的那样,我的数据不会没有坚持。但是当我评论这些行时(将两个属性设置为true),我的所有数据都会返回(持续存在)。任何想法 ? – Ohmy