Swift Core Data - массивы загружаются неправильно - PullRequest
2 голосов
/ 23 января 2020

Я пытаюсь реализовать простую функциональную функцию для моего приложения с 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;

Так что я не уверен, существует ли проблема при сохранении или загрузка элементов.

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 голос
/ 24 января 2020

Удостоверьтесь, что ваша категория -> отношение предметов - 1-ко-многим. Вероятно, сейчас происходит то, что у вас есть один к одному, поэтому каждый раз, когда вы устанавливаете родительскую категорию для нового элемента, она сбрасывает предыдущий.

Также вместо

let categoryPredicate = NSPredicate(format :"parentCategory.name MATCHES %@",selectedCategory!.name!)

просто делайте

let categoryPredicate = NSPredicate(format :"parentCategory = %@", selectedCategory!)
...