Как отредактировать строку в TableView и сохранить изменения в CoreData?

#ios #swift #uitableview #core-data

#iOS #swift #uitableview #core-данные

Вопрос:

Я создал простой ToDoList с простым CoreData. Добавлено создание строки, удаление строки, но невозможно изменить строку. Я не могу понять, как это сделать.

Я добавил AlertController, чтобы изменить его.

Мои CoreData состоят из одного свойства: name . И я создаю интерфейс без раскадровки, просто код. Как обновить объект CoreData?

 import UIKit
import CoreData

class ViewController: UITableViewController {

    private let cellID = "cell"
    private var tasks = [Task]() 

    private let appDelegate = UIApplication.shared.delegate as! AppDelegate // 

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .white

        title = "To do list"

        navigationController?.navigationBar.barTintColor = UIColor(displayP3Red: 21/255,
                                                                   green: 101/255,
                                                                   blue: 192/255,
                                                                   alpha: 1)

        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add",
                                                            style: .plain,
                                                            target: self,
                                                            action: #selector(addNewTask))

        navigationController?.navigationBar.tintColor = .white

        tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellID)

    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        let managedContext = appDelegate.persistentContainer.viewContext 
        let fetchRequest: NSFetchRequest<Task> = Task.fetchRequest() 

        do {
            tasks = try managedContext.fetch(fetchRequest)
        } catch let error {
            print("Failed to fetch data", error)
        }
    }

    // MARK: Table View Data Source

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tasks.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath)

        let task = tasks[indexPath.row]
        cell.textLabel?.text = task.name

        return cell
    }

    override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

        let editNotesAction = UITableViewRowAction(style: .default, title: "Edit") { (action: UITableViewRowAction, indexPath: IndexPath) in

            let alert = UIAlertController(title: "Edit", message: "", preferredStyle: .alert)

            let saveAction = UIAlertAction(title: "Save", style: .default, handler: { (action) in

            })

            let cancelAction = UIAlertAction(title: "Cancel", style: .default)
            alert.addTextField()
            alert.addAction(saveAction)
            alert.addAction(cancelAction)
            self.present(alert, animated: true)
        }

        editNotesAction.backgroundColor = .blue

        let deleteNotesAction = UITableViewRowAction(style: .default, title: "Delete") { (action: UITableViewRowAction, indexPath: IndexPath) in

            let managedContext = self.appDelegate.persistentContainer.viewContext

            managedContext.delete(self.tasks[indexPath.row])

            self.tasks.remove(at: indexPath.row)

            do {
                try managedContext.save()
            } catch let error {
                print(error.localizedDescription)
            }
            self.tableView.deleteRows(at: [indexPath], with: .fade)
        }

        return [deleteNotesAction, editNotesAction]
    }

    @objc private func addNewTask() {

        let alert = UIAlertController(title: "New Task", message: "", preferredStyle: .alert)

        let saveAction = UIAlertAction(title: "Save", style: .default) { _ in

            guard let task = alert.textFields?.first?.text, task.isEmpty == false else { return }

            self.saveData(task)

            self.tableView.reloadData()
        }

        let cancelAction = UIAlertAction(title: "Cancel", style: .destructive)

        alert.addTextField() 
        alert.addAction(saveAction) 
        alert.addAction(cancelAction) 

        present(alert, animated: true) 
    }

    private func saveData(_ taskName: String) {

        let managedContext = appDelegate.persistentContainer.viewContext 
        guard let entity = NSEntityDescription.entity(forEntityName: "Task", in: managedContext) else { return } 
        let task = NSManagedObject(entity: entity, insertInto: managedContext) as! Task 
        task.name = taskName 
        do {
            try managedContext.save()
            tasks.append(task)
        } catch let error {
            print("Failed to save task", error.localizedDescription)
        }
    }
}
  

Ответ №1:

Ваше действие сохранения должно извлечь значение из текстового поля и присвоить его правильному управляемому объекту.

 let saveAction = UIAlertAction(title: "Save", style: .default, handler: { (action) in
    guard let textField = alert.textFields.first else { return }
    let task = tasks[indexPath.row]
    task.name = textField.text
})
  

Если name это необязательно, вам нужно будет использовать nil-coalescing для указания значения по умолчанию для имени, если текстовое поле пустое. ( task.name = textField.text ?? "SomeDefaultName" )