'How to disable Done button if I have empty textField datePicker pass data in detailTextLabel

I have two View Controller. The first one is MyListOfTasksVC and the second one is AddAndEditVC. In the second VC i have a date picker and pass date to subtitle lable in cellForRowAt. Before implementing that my Done button was disabled if textField is empty. But now datePicker ignores that and adds new row with just date.

How I can disable Done button in such situation? I tried to make delegate, but it wasn't successful.

//in MyListOfTasksVC

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyDailyTasksCell", for: indexPath)
    
    let item = items[indexPath.row]
    configureText(for: cell, with: item)
    configureCheckmark(for: cell, with: item)
    
    let date = items[indexPath.row].date
    let formatter = DateFormatter()
    formatter.dateFormat = "MMM d, h:mm a"
    cell.detailTextLabel?.text = formatter.string(from: date)
    return cell
}


Solution 1:[1]

It looks like what you're trying to build is a todo-list app that prevents the user from entering a task item without a title.

Your first view controller, MyListOfTasksVC, displays all the tasks which have already been added.

Your second view controller, AddAndEditVC, has a UITextField for entering a new task's title and a UIDatePicker to set a deadline for the task. Somewhere on the second view controller, there is a 'DONE' button that creates an Item struct with the text from the UITextField as the .title property and the date from the UIDatePicker as the .date property. This struct then gets passed back to MyListOfTasksVC and appended to the array items, and is displayed as another task in the UITableView.

The question you're asking seems to be, "How to disable this button if the value of textField.text is nil or the empty string?"

The simplest way I know of is to set the 'DONE' button's isEnabled property inside your UITextFieldDelegate method textFieldDidEndEditing. If the value of your text field's text is nil or "", set doneButton.isEnabled = false. Otherwise, doneButton.isEnabled = true. This way, the button only allows submitting the new task if it has a title.

Here is what I had inside AddAndEditVC:

import UIKit

class AddAndEditVC: UIViewController {
    @IBOutlet weak var taskNameField: UITextField!
    @IBOutlet weak var datePicker: UIDatePicker!
    @IBOutlet weak var doneButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        doneButton.isEnabled = false
        taskNameField.delegate = self
    }

    @IBAction func addNewTask(_ sender: UIButton) {
        self.performSegue(withIdentifier: "backToTasksList", sender: self)
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let newItem = Item(title: taskNameField.text!, date: datePicker.date)
        let destinationVC = segue.destination as! MyListOfTasksVC
        destinationVC.newItem = newItem
    }
}

extension AddAndEditVC: UITextFieldDelegate {
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.endEditing(true)
        return true
    }
    
    func textFieldDidEndEditing(_ textField: UITextField) {
        if textField.text != nil && textField.text != "" {
            doneButton.isEnabled = true
        } else {
            doneButton.isEnabled = false
        }
    }
}

and here is MyListOfTasksVC:

import UIKit

struct Item {
    var title: String
    var date: Date
}

class MyListOfTasksVC: UIViewController {
    @IBOutlet weak var tasksTable: UITableView!
    
    var newItem: Item?
    
    var items: [Item] = [Item(title: "Wake Up", date: Date()), Item(title: "Feed Dog", date: Date()), Item(title: "Finish Report", date: Date())]

    override func viewDidLoad() {
        super.viewDidLoad()
        tasksTable.dataSource = self
        
        if newItem != nil {
            items.append(newItem!)
        }
    }

    @IBAction func toAddAndEditScreen(_ sender: UIButton) {
        self.performSegue(withIdentifier: "toAddAndEdit", sender: self)
    }
}

extension MyListOfTasksVC: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "MyDailyTasksCell", for: indexPath)
        
        let item = items[indexPath.row]
        //configureText(for: cell, with: item)
        //configureCheckmark(for: cell, with: item)
        
        cell.textLabel?.text = item.title
        
        let date = items[indexPath.row].date
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM d, h:mm a"
        cell.detailTextLabel?.text = formatter.string(from: date)
        return cell
    }
}

Is this the functionality you're looking for?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Quack E. Duck