SpaceX
SpaceX

Reputation: 2890

Unable to update time in datePicker on button click in tableview swift

I am trying to display a date picker and update its time on button click.

I have a table view which shows business hours as shown in the below figure 1.

Figure 1

enter image description here

On clicking the timings cell or the time button inside the cell, I am expanding the cell to show date picker, I am unable to update the time in the date picker to the time on the time button.

For example when 9:00 AM is clicked, I would like to show 9:00 AM in the date picker as shown in below figure 2 or when 5:00 PM is clicked I would like to show 5:00 PM in date picker.

Also when the user changes the time in the date picker, I would like to update its corresponding time button in the tableview cell.

Figure 2

enter image description here

Below is the code, see code below comment //Updating the date picker

Since I am trying to update the date picker time inside a closure, it doesn't seem to work. Can someone please advice how I can fix this ?

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        tableView.setEditing(true, animated: true)      // This displays the delete button infront of the cell
        tableView.allowsSelectionDuringEditing = true   // Allows the table view cells to be selected during editing mode

        if indexPath.section == 0 {

            let cell = Bundle.main.loadNibNamed("DailyTimesTableViewCell", owner: self, options: nil)?.first as! DailyTimesTableViewCell

            // Configure the cell...
            cell.selectionStyle             = UITableViewCellSelectionStyle.none; // Ensuring that there is no background for the selected cell
            cell.datePicker.datePickerMode  = .time         // Setting start and time            
            cell.datePicker.minuteInterval = 5
            cell.datePicker.addTarget(self, action: #selector(datePickerChanged), for: .valueChanged)

            let startTime   = timesArray[indexPath.row]["startTime"]
            cell.startTime.setTitle(startTime as! String?, for: .normal)
            cell.startTime.setTitleColor(UIColor.black, for: .normal)

            let endTime     = timesArray[indexPath.row]["endTime"]

            cell.endTime.setTitle(endTime as! String?, for: .normal)
            cell.endTime.setTitleColor(UIColor.black, for: .normal)

            // Closure
            cell.startTimeTapped = { (button  : UIButton) -> Void in

                // Updating the date picker 
                cell.datePicker.date = self.convertToDateObject(timeString: startTime as! String)
                tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.automatic)

                // Expanding the cell to show date picker 
                if self.selectedCellIndexPath != nil && self.selectedCellIndexPath == indexPath {
                    tableView.cellForRow(at: indexPath)?.setEditing(true, animated: true)   // This displays the delete button infront of the cell
                    self.selectedCellIndexPath = nil
                } else {
                    self.selectedCellIndexPath = indexPath
                }


            }

            // Closure
            cell.endTimeTapped = { (button) -> Void in
                // Updating the date picker
                cell.datePicker.date = self.convertToDateObject(timeString: endTime as! String)
                tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.automatic)

                // Expanding the cell to show date picker 
                if self.selectedCellIndexPath != nil && self.selectedCellIndexPath == indexPath{
                    tableView.cellForRow(at: indexPath)?.setEditing(true, animated: true)
                    self.selectedCellIndexPath = nil
                }else{
                    self.selectedCellIndexPath = indexPath
                }
            }
            return cell
      }
}

DailyTimesTableViewCell code:

import UIKit

class DailyTimesTableViewCell: UITableViewCell, UITableViewDelegate {
    typealias  buttonTappedBlock = (_ button:UIButton) -> Void
    var startTimeTapped : buttonTappedBlock!
    var endTimeTapped : buttonTappedBlock!



    @IBAction func startTimeClicked(_ sender: subclassedUIButton) {
        if startTimeTapped != nil {
            startTimeTapped(sender as UIButton)
        }
    }

    @IBAction func endTimeClicked(_ sender: UIButton) {
        if endTimeTapped != nil{
            endTimeTapped(sender as UIButton)
        }
    }
}

Upvotes: 0

Views: 1088

Answers (2)

SpaceX
SpaceX

Reputation: 2890

The answer for this part of the question:

I am unable to update the time in the date picker to the time on the time button

is the below code:

the issue was with this line of code tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.automatic) and by adding tableView.beginUpdates(), tableView.beginUpdates() and returning the cell helped.

In the function cellForRow At updated to the below code

cell.startTimeTapped = { (button) -> DailyTimesTableViewCell in
                self.tableView.beginUpdates()
                cell.datePicker.date = self.convertToDateObject(timeString: startTime as! String)
                if self.selectedCellIndexPath != nil && self.selectedCellIndexPath == indexPath {
                    tableView.cellForRow(at: indexPath)?.setEditing(true, animated: true)   // This displays the delete button infront of the cell
                    self.selectedCellIndexPath = nil
                } else {
                    self.selectedCellIndexPath = indexPath
                }

                tableView.endUpdates()

                return cell

            }

In the class DailyTimesTableViewCell, updated to the below code

class DailyTimesTableViewCell: UITableViewCell, UITableViewDelegate {

typealias  buttonTappedBlock = (_ button:UIButton) -> DailyTimesTableViewCell
    var startTimeTapped : buttonTappedBlock!
    var endTimeTapped : buttonTappedBlock!
    @IBAction func startTimeClicked(_ sender: UIButton) {

        if startTimeTapped != nil {
            startTimeTapped(sender as UIButton)
        }
   }

}

Upvotes: 0

Fangming
Fangming

Reputation: 25280

To set date for your UIDatePicker, simply use this piece of code to convert string formed time to a date

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat =  "HH:mm"
let date = dateFormatter.dateFromString("17:00")//Put textfield.text! here

datePicker.date = date

For your second part of the question, since you may have multiple date pickers, what you need to do is to add selection change listener to all of them, then figure out which one is changed and also which label is clicked. Finally set the label to correct value.

You can use section number to find out which data picker is clicked. In your cellForRow, add section as tag and then add the listener

datePicker.tag = indexPath.section
textView.tag = indexPath.section
datePicker.addTarget(self, action: Selector("dataPickerChanged:"), forControlEvents: UIControlEvents.ValueChanged)

Then in the listener function, find out which data picker has changed value

func datePickerChanged(datePicker:UIDatePicker) {
    var dateFormatter = NSDateFormatter()
    dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
    dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle

    if datePicker.tag == 0 {
        textView.text = dateFormatter.stringFromDate(datePicker.date)
    }
    // keep going

}

Upvotes: 1

Related Questions