Swift 核心数据 - 数组未正确加载
Swift Core Data - arrays not loading properly
我正在尝试使用 Core Data 为我的应用程序实现一个简单的待办事项功能,但我无法加载添加的项目数组。待办事项有 2 个视图(类别视图和相应的项目视图)。我实现了 NSPredicate 来根据类别过滤我们相应的项目,但它 只加载最后添加的项目 。当我删除谓词时,它会清楚地显示每个添加的项目。
此外,当我添加一个新数组时,我注意到调试区域中之前添加的项目出错:
error save context Error Domain=NSCocoaErrorDomain Code=1570 "parentCategory is a required value." UserInfo={NSValidationErrorObject=<Echieve.Item: 0x6000019fc410> (entity: Item; id: 0xdb0af4c047f4bf03 <x-coredata://F4D9D28E-242A-4BEE-A528-C067AF1F8909/Item/p89>; data: {
done = 0;
parentCategory = nil;
title = 1111;
所以我不确定是保存还是载入Items有问题
var itemArray = [Item]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var selectedCategory: Category? {
didSet {
loadItems()
}
}
override func viewDidLoad() {
super.viewDidLoad()
loadItems()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
let item = itemArray[indexPath.row]
cell.textLabel?.text = item.title
cell.accessoryType = item.done ? .checkmark : .none
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
itemArray[indexPath.row].done = !itemArray[indexPath.row].done
saveItems()
tableView.deselectRow(at: indexPath, animated: true)
}
override func updateModel(at index: IndexPath) {
context.delete(itemArray[index.row])
itemArray.remove(at: index.row)
saveItems()
}
@IBAction func addNewItem(_ sender: Any) {
var alertTextField = UITextField()
let alert = UIAlertController(title: "Add new Item", message: "", preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "enter the name"
alertTextField = textField
}
let action = UIAlertAction(title: "Add new Item", style: .default) { (action) in
let newItem = Item(context: self.context)
newItem.title = alertTextField.text!
newItem.done = false
newItem.parentCategory = self.selectedCategory
self.itemArray.append(newItem)
self.saveItems()
}
let cancel = UIAlertAction(title: "Cancel", style: .default) { (action) -> Void in
print("Cancel button tapped")
}
alert.addAction(action)
alert.addAction(cancel)
present(alert,animated: true,completion: nil)
tableView.reloadData()
}
func saveItems() {
do {
try context.save()
} catch {
print("error save context \(error) ")
}
tableView.reloadData()
}
func loadItems(with request: NSFetchRequest<Item> = Item.fetchRequest() , predicate : NSPredicate? = nil)
{
let categoryPredicate = NSPredicate(format :"parentCategory.name MATCHES %@",selectedCategory!.name!)
//print(categoryPredicate)
if let additionalPredicate = predicate
{
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [categoryPredicate , additionalPredicate])
}
else
{
request.predicate = categoryPredicate
}
print(request.predicate!)
do{
itemArray = try context.fetch(request)
}
catch
{
print("error when fetch result \(error)")
}
tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadItems()
}
非常感谢您的任何建议。
确保您的类别 -> 项目关系是一对多。可能现在发生的情况是您有 1 对 1,所以每次您在新项目上设置父类别时,它都会取消设置前一个。
也代替了
let categoryPredicate = NSPredicate(format :"parentCategory.name MATCHES %@",selectedCategory!.name!)
就这样
let categoryPredicate = NSPredicate(format :"parentCategory = %@", selectedCategory!)
我正在尝试使用 Core Data 为我的应用程序实现一个简单的待办事项功能,但我无法加载添加的项目数组。待办事项有 2 个视图(类别视图和相应的项目视图)。我实现了 NSPredicate 来根据类别过滤我们相应的项目,但它 只加载最后添加的项目 。当我删除谓词时,它会清楚地显示每个添加的项目。
此外,当我添加一个新数组时,我注意到调试区域中之前添加的项目出错:
error save context Error Domain=NSCocoaErrorDomain Code=1570 "parentCategory is a required value." UserInfo={NSValidationErrorObject=<Echieve.Item: 0x6000019fc410> (entity: Item; id: 0xdb0af4c047f4bf03 <x-coredata://F4D9D28E-242A-4BEE-A528-C067AF1F8909/Item/p89>; data: {
done = 0;
parentCategory = nil;
title = 1111;
所以我不确定是保存还是载入Items有问题
var itemArray = [Item]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var selectedCategory: Category? {
didSet {
loadItems()
}
}
override func viewDidLoad() {
super.viewDidLoad()
loadItems()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
let item = itemArray[indexPath.row]
cell.textLabel?.text = item.title
cell.accessoryType = item.done ? .checkmark : .none
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
itemArray[indexPath.row].done = !itemArray[indexPath.row].done
saveItems()
tableView.deselectRow(at: indexPath, animated: true)
}
override func updateModel(at index: IndexPath) {
context.delete(itemArray[index.row])
itemArray.remove(at: index.row)
saveItems()
}
@IBAction func addNewItem(_ sender: Any) {
var alertTextField = UITextField()
let alert = UIAlertController(title: "Add new Item", message: "", preferredStyle: .alert)
alert.addTextField { (textField) in
textField.placeholder = "enter the name"
alertTextField = textField
}
let action = UIAlertAction(title: "Add new Item", style: .default) { (action) in
let newItem = Item(context: self.context)
newItem.title = alertTextField.text!
newItem.done = false
newItem.parentCategory = self.selectedCategory
self.itemArray.append(newItem)
self.saveItems()
}
let cancel = UIAlertAction(title: "Cancel", style: .default) { (action) -> Void in
print("Cancel button tapped")
}
alert.addAction(action)
alert.addAction(cancel)
present(alert,animated: true,completion: nil)
tableView.reloadData()
}
func saveItems() {
do {
try context.save()
} catch {
print("error save context \(error) ")
}
tableView.reloadData()
}
func loadItems(with request: NSFetchRequest<Item> = Item.fetchRequest() , predicate : NSPredicate? = nil)
{
let categoryPredicate = NSPredicate(format :"parentCategory.name MATCHES %@",selectedCategory!.name!)
//print(categoryPredicate)
if let additionalPredicate = predicate
{
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [categoryPredicate , additionalPredicate])
}
else
{
request.predicate = categoryPredicate
}
print(request.predicate!)
do{
itemArray = try context.fetch(request)
}
catch
{
print("error when fetch result \(error)")
}
tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadItems()
}
非常感谢您的任何建议。
确保您的类别 -> 项目关系是一对多。可能现在发生的情况是您有 1 对 1,所以每次您在新项目上设置父类别时,它都会取消设置前一个。
也代替了
let categoryPredicate = NSPredicate(format :"parentCategory.name MATCHES %@",selectedCategory!.name!)
就这样
let categoryPredicate = NSPredicate(format :"parentCategory = %@", selectedCategory!)