Hi, I'm going over the - Hotel Manzana - project in "Develop in Swift - Data Collections". The app is for the registration and room assignment for a hotel. I must include the Check In date and the Check out date for the which I'm using a date picker for both set in a 4 row section in a table view just like in the next image:
When running the app the Date pickers must be hidden. And to activate one must press the check in or check out section just like this:
Only one date picker must be shown at a time for which if I select one and the other is shown, then only the one I selected must be shown and the other must be hidden. However at the time of execution I can only open one Date Picker and close it one time. After that it won't show me neither of the date pickers again, no matter how much I press the check in or check out rows in the table view, they'll stay hidden after the first time I opened them...
My code is as follows:
class AddRegistrationTableViewController: UITableViewController {
@IBOutlet weak var firstNameTextField: UITextField!
@IBOutlet weak var lastNameTextField: UITextField!
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var checkInDateLabel: UILabel!
@IBOutlet weak var checkInDatePicker: UIDatePicker!
@IBOutlet weak var checkOutDateLabel: UILabel!
@IBOutlet weak var checkOutDatePicker: UIDatePicker!
var formattedDate: DateFormatter = {
let formattedDate = DateFormatter()
formattedDate.dateStyle = .medium
return formattedDate
}()
let checkInDateLabelCellIndexPath = IndexPath(row: 0, section: 1)
let checkInDatePickerCellIndexPath = IndexPath(row: 1, section: 1)
let checkOutDateLabelCellIndexPath = IndexPath(row: 2, section: 1)
let checkOutDatePickerCellIndexPath = IndexPath(row: 3, section: 1)
var isCheckInDatePickerVisible: Bool = false {
didSet {
checkInDatePicker.isHidden = !isCheckInDatePickerVisible
}
}
var isCheckOutDatePickerVisible: Bool = false {
didSet {
checkOutDatePicker.isHidden = !isCheckOutDatePickerVisible
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
let midnight = Calendar.current.startOfDay(for: Date())
checkInDatePicker.minimumDate = midnight
checkInDatePicker.date = midnight
updateDateViews()
}
func updateDateViews() {
checkOutDatePicker.minimumDate = Calendar.current.date(byAdding: .day, value: 1, to: checkInDatePicker.date)
checkInDateLabel.text = formattedDate.string(from: checkInDatePicker.date)
checkOutDateLabel.text = formattedDate.string(from: checkOutDatePicker.date)
}
@IBAction func doneBarButtonTapped(_ sender: UIBarButtonItem) {
let firstName = firstNameTextField.text ?? ""
let lastName = lastNameTextField.text ?? ""
let email = emailTextField.text ?? ""
let checkInDate = checkInDatePicker.date
let checkOutDate = checkOutDatePicker.date
print("firstName: \(firstName)")
print("lastName: \(lastName)")
print("email: \(email)")
print("checkInDate: \(checkInDate)")
print("checkOutDate: \(checkOutDate)")
}
@IBAction func datePickerValueChanged(_ sender: UIDatePicker) {
updateDateViews()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch indexPath {
case checkInDatePickerCellIndexPath where isCheckInDatePickerVisible == false:
return 0
case checkOutDatePickerCellIndexPath where isCheckOutDatePickerVisible == false:
return 0
default:
return UITableView.automaticDimension
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if indexPath == checkInDateLabelCellIndexPath && isCheckOutDatePickerVisible == false {
isCheckInDatePickerVisible.toggle()
if checkInDatePicker.isHidden == false {
print("Check in date picker visible")
} else {
print("Check in date picker not visible")
}
} else if indexPath == checkOutDateLabelCellIndexPath && isCheckInDatePickerVisible == false {
isCheckOutDatePickerVisible.toggle()
if checkOutDatePicker.isHidden == false {
print("Check out date picker visible")
} else {
print("Check out date picker not visible")
}
} else if indexPath == checkInDateLabelCellIndexPath || indexPath == checkOutDateLabelCellIndexPath {
isCheckInDatePickerVisible.toggle()
isCheckOutDatePickerVisible.toggle()
} else {
return
}
tableView.beginUpdates()
tableView.endUpdates()
}
As you can see in tableView(_: didSelectRow) I added two conditional if statements to print to the console if either isCheckInDatePickerVisible
and isCheckOutDatePicker
are visible or not.
Both of these do work and actually tell me that the value really is changing but my interface won't update and show me the date pickers more than one time .
I do not see in your code where is tableView(cellForRow) ?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
.
The simplest would be to manage all this with your dataSource.
var pickers : [DatePicker] = []
In your code, you would have
pickers = [checkInDatePicker]
or
pickers = [checkOutDatePicker]
Note a question: why do you need to define isCheckOutDatePickerVisible and not use simply isCheckOutDatePicker.isHidden
For instance,
} else if indexPath == checkOutDateLabelCellIndexPath && isCheckInDatePickerVisible == false {
would become
} else if indexPath == checkOutDateLabelCellIndexPath && icheckInDatePicker.isHidden {
Or
isCheckInDatePickerVisible.toggle()
would become
checkInDatePicker.isHidden.toggle()
That could simplify code a lot.
Now a hint.
Why do you:
tableView.beginUpdates()
tableView.endUpdates()
with nothing inside
And not simply
tableView.reload()