在將我的應用程序升級到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