问题描述
我的目标是在编辑文本后按下完成按钮来更新核心数据中的对象。
完成按钮和下面的文本字段:
这是我的一些代码,
@objc func doneTapped() {
do {
try context.save()
} catch {
print("Error saving the new information \(error)")
}
dateEditableTextF.resignFirstResponder()
selectedEventDate = dateEditableTextF.text
dateEditableTextF.isEnabled = false
costEditableTextF.resignFirstResponder()
selectedEventCost = costEditableTextF.text
costEditableTextF.isEnabled = false
gradesEditableTextF.resignFirstResponder()
selectedEventGrade = gradesEditableTextF.text
gradesEditableTextF.isEnabled = false
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit,target: self,action: #selector(editTapped))
}
我希望当我在编辑文本字段后运行应用程序时按下完成按钮时,信息会更新,而当我返回到视图控制器时,信息会相同并且我的核心数据数据库会更新具有该对象的更新属性。
实际发生的情况是,当我完成编辑文本字段时,视图控制器中的数据会更新,但是当我离开视图控制器并返回时,数据会恢复到旧条目。
我看了大约 4 个关于 crud 方法的 youtube 视频,它们都是不同的场景,与我的不匹配,所以我希望这里有人可以提供帮助。提前致谢。
这是我的视图控制器的其余部分。
@IBOutlet weak var costEditableTextF: UITextField!
@IBOutlet weak var dateEditableTextF: UITextField!
@IBOutlet weak var gradesEditableTextF: UITextField!
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var updateTheEvents = [Event]()
var selectedEventName: String?
var selectedEventDate: String?
var selectedEventCost: String?
var selectedEventGrade: String?
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = selectedEventName
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit,action: #selector(editTapped))
if let datetoLoad = selectedEventDate {
dateEditableTextF.text = selectedEventDate
}
if let costToLoad = selectedEventCost {
costEditableTextF.text = selectedEventCost
}
if let gradesToLoad = selectedEventGrade {
gradesEditableTextF.text = selectedEventGrade
}
// Do any additional setup after loading the view.
}
@objc func editTapped() {
dateEditableTextF.becomeFirstResponder()
dateEditableTextF.isEnabled = true
costEditableTextF.isEnabled = true
gradesEditableTextF.isEnabled = true
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done,action: #selector(doneTapped))
}
解决方法
首先你需要创建一个存储来管理你的persistentContainer和CRUD操作:
class PersistenceManager {
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "your_xcdatamodeld_name") //Here you should type the name of your xcdatamodeld file without the extension .xcdatamodeld
container.loadPersistentStores(completionHandler: { (storeDescription,error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error),\(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
return container
}()
}
现在要保存数据,您需要一个上下文。我强烈建议你使用全局的。我在从外部函数访问商店上下文时遇到了几个问题(即没有添加/编辑东西)。请注意,尽管它对我很有用,但我不确定全局上下文是否是最佳实践。不过,我还遇到了任何问题。
在您的 PersistenceManager
类中,在persistentContainer 之前放置以下代码
static let shared = PersistenceManager()
var managedObjectContext: NSManagedObjectContext {
persistentContainer.viewContext
}
并且,在课前和课外放以下内容
let context = PersistenceManager.shared.managedObjectContext
...
class PersistenceManager { [...] }
现在您必须像这样创建保存功能:
func saveContext () {
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror),\(nserror.userInfo)")
}
}
这在 PersistenceManager
类中。
现在是有趣的部分:您必须创建 CRUD 函数。这些都将在您的 PersistenceManager 类中。我将向您展示一个关于创建和编辑实体的小演示。
假设您有一个名为“Item”的实体,它具有属性 name 和 price。
要保存每个项目,您将拥有如下功能:
func creaateNewItem(name: String,price: Int) -> Item {
let entity = NSEntityDescription.entity(forEntityName: Item,in: context)
let newItem = Item(entity: entity!,insertInto: context)
newItem.name = name
newItem.price = price
self.saveContext()
return newItem
}
要编辑项目,您必须获取它,然后为其分配新值:
func editItem(currentItem: Item,newName: String,newPrice: Int) {
let currentName: String = currentItem.name! //Current name
//Looking for the item to edit
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")
request.predicate = NSPredicate(format: "name = %@",currentName)
request.returnsObjectsAsFaults = false
do { //Editing the item
let editedItem = (try context.fetch(request))[0] as! Item
editedItem.name = newName
editedItem.price = newPrice
self.saveContext()
} catch let error {
print("Error \n \((error))")
}
}
正如你在这里看到的,我传递了一些参数,允许你自定义你的项目。显然,如果您需要分配默认值,您可以删除这些参数。
现在,在您的视图控制器中,您将创建一个 Item
数组对象:
my item : [Item]?
里面会装满你的物品。
要通过按条形按钮来编辑您保存的项目,您现在只需执行以下操作:
@objc func editMyItem(){
let newName = "Edited Item"
let newPrice = 15
PersistenceManager().editItem(currentItem: item[indexOfYourChoice],newName: newName,newPrice: newPrice)
}
您的项目将被编辑!
请注意,例如,如果您希望文本来自文本字段,则 newPrice
常量将等于该文本字段的文本。