I am creating a ToDo List application.
I used tableView to list tasks. And I use my own class for the cell. In cellViewView I have a shortcut and one button made in it. I successfully performed the click action in my code. It works great.
Problem
When I click the Finish button, it deletes the last added task. But did not click. And when I repeat to click the Finish button, it takes no action. How to resolve this error
GIF added below, click the link

ToDo Entity Class
import Foundation import CoreData p>
public class ToDo: NSManagedObject {
public override func awakeFromInsert() {
self.created = NSDate()
}
}
Mainvc
import UIKit
import CoreData
class MainVC: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate {
var controller: NSFetchedResultsController<ToDo>!
@IBOutlet weak var taskTextField: CustomTextField!
@IBOutlet weak var tableView: UITableView!
var toDo: ToDo!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
attemptFetch()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! ItemCell
configureCell(cell: cell, indexPath: indexPath as NSIndexPath)
return cell
}
func configureCell(cell: ItemCell, indexPath: NSIndexPath) {
let toDo = controller.object(at: indexPath as IndexPath)
cell.configureCell(toDo: toDo)
cell.doneBtn.tag = indexPath.row
cell.doneBtn.addTarget(self, action: #selector(MainVC.donePressed), for: UIControlEvents.touchUpInside)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let task = objs[indexPath.row]
performSegue(withIdentifier: "ItemDetailsVC", sender: task)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ItemDetailsVC" {
if let destination = segue.destination as? ItemDetailsVC {
if let task = sender as? ToDo {
destination.taskDetails = task
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = controller.sections {
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects
}
return 0
}
func numberOfSections(in tableView: UITableView) -> Int {
if let sections = controller.sections {
return sections.count
}
return 0
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70
}
func attemptFetch() {
let fetchRequest: NSFetchRequest<ToDo> = ToDo.fetchRequest()
let dateSort = NSSortDescriptor(key: "created", ascending: true)
fetchRequest.sortDescriptors = [dateSort]
let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = self
self.controller = controller
do {
try controller.performFetch()
} catch {
let error = error as NSError
print("\(error)")
}
}
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case.insert:
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break
case.delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
break
case.update:
if let indexPath = indexPath {
let cell = tableView.cellForRow(at: indexPath)
configureCell(cell: cell as! ItemCell, indexPath: indexPath as NSIndexPath)
}
break
case.move:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break
}
}
@IBAction func addBtnPressed(_ sender: UIButton) {
if taskTextField.text != "" && taskTextField.text != nil {
toDo = ToDo(context: context)
if let task = taskTextField.text {
toDo.title = task
}
ad.saveContext()
taskTextField.text = ""
self.tableView.reloadData()
}
}
func donePressed() {
if toDo != nil {
context.delete(toDo)
ad.saveContext()
}
}
func generateData() {
let task = ToDo(context: context)
task.title = "alwin"
let task1 = ToDo(context: context)
task1.title = "rambo"
let task2 = ToDo(context: context)
task2.title = "monisha"
let task3 = ToDo(context: context)
task3.title = "wounderlist"
let task4 = ToDo(context: context)
task4.title = "presentation"
let task5 = ToDo(context: context)
task5.title = "roundup"
ad.saveContext()
}
}
ItemDetailsVC
import UIKit
class ItemDetailsVC: UIViewController {
var taskDetails: ToDo?
@IBOutlet weak var detailsLbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
if let topItem = self.navigationController?.navigationBar.topItem {
topItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
if taskDetails != nil {
loadItemData()
}
}
}
func loadItemData() {
if let task = taskDetails {
detailsLbl.text = task.title
}
}
override func viewDidLayoutSubviews() {
detailsLbl.sizeToFit()
}
@IBAction func deletePressed(_ sender: UIBarButtonItem) {
if taskDetails != nil {
context.delete(taskDetails!)
ad.saveContext()
}
_ = navigationController?.popViewController(animated: true)
}
}
storyboard, click the link below

ItemCell
import UIKit
class ItemCell: UITableViewCell {
@IBOutlet weak var taskTitle: UILabel!
@IBOutlet weak var doneBtn: UIButton!
var toDo: ToDo?
func configureCell(toDo: ToDo) {
taskTitle.text = toDo.title
}
}