Right here is the code that I’ve carried out in native iOS Swift:
class DateFilterViewController: BaseViewController, DateFilterView {
// MARK: - Non-public properties
@IBOutlet weak var crossButton: UIButton?
@IBOutlet weak var segmentView: UIView?
@IBOutlet weak var startLabel: UILabel?
@IBOutlet weak var startDateField: BorderedTextField?
@IBOutlet weak var endLabel: UILabel?
@IBOutlet weak var endDateField: BorderedTextField?
@IBOutlet weak var mainButton: UIButton?
var segementControl: UISegmentedControl?
personal let look: DateFilterAppearance?
personal let datePickerStart = UIDatePicker()
personal let datePickerEnd = UIDatePicker()
personal var isSelectedSegment = false
personal var startSelectedDate = Date()
personal var endSelectedDate = Date()
personal let sprint = DateUtil.dashDataFormat, slash = DateUtil.slashDataFormat
// MARK: - Public properties
var output: DateFilterViewOutput!
// MARK: - Initialization / Deinitialization
init(look: DateFilterAppearance?) {
self.look = look
tremendous.init(nibName: "DateFilterView", bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been applied")
}
// MARK: - UIViewController
override func viewDidLoad() {
tremendous.viewDidLoad()
title = localizedKey(key: "title")
self.navigationController?.isNavigationBarHidden = false
if let show = self.look {
setViewAppearance(look: show)
}
startDateField?.dropdownButton(completionHandler: {
if let subject = self.startDateField {
self.callDatePicker(textField: subject)
}
})
endDateField?.dropdownButton(completionHandler: {
if let subject = self.endDateField {
self.callDatePicker(textField: subject)
}
})
}
// MARK: - DateFilterView
var dates: [Dates]? = [] {
didSet {
}
}
var confirmDates: Dates? {
didSet {
output.confirmDates = confirmDates
}
}
personal func callDatePicker(textField: UITextField) {
textField.keyboardToolbar.tintColor = UIColor.black
if textField == startDateField {
datePickerStart.datePickerMode = UIDatePicker.Mode.date
if #out there(iOS 13.4, *) {
datePickerStart.preferredDatePickerStyle = .wheels
}
textField.becomeFirstResponder()
textField.inputView = datePickerStart
datePickerStart.addTarget(self, motion: #selector(handleStartDatePicker), for: UIControl.Occasion.valueChanged)
textField.addDoneOnKeyboardWithTarget(self, motion: #selector(donePickerStart))
if let sDate = showSelectedDate(textField: textField) {
datePickerStart.date = sDate
}
} else {
datePickerEnd.datePickerMode = UIDatePicker.Mode.date
if #out there(iOS 13.4, *) {
datePickerEnd.preferredDatePickerStyle = .wheels
}
textField.becomeFirstResponder()
textField.inputView = datePickerEnd
datePickerEnd.addTarget(self, motion: #selector(handleEndDatePicker), for: UIControl.Occasion.valueChanged)
textField.addDoneOnKeyboardWithTarget(self, motion: #selector(donePickerEnd))
if let eDate = showSelectedDate(textField: textField) {
datePickerEnd.date = eDate
}
}
}
personal func showSelectedDate(textField: UITextField) -> Date? {
if let sDateString = textField.textual content, sDateString.depend > 0 {
return DateUtil.getDateFromString(string: sDateString, timeFormat: DateUtil.slashDataFormat)
}
return nil
}
// MARK: - Non-public strategies
@objc personal func donePickerStart() {
self.view.endEditing(true)
guard let sDate = startDateField?.textual content, !sDate.isEmpty else {
self.startDateField?.textual content = DateUtil.convertStringFromDate(date: datePickerStart.date)
return
}
}
@objc personal func donePickerEnd() {
self.view.endEditing(true)
guard let eDate = endDateField?.textual content, !eDate.isEmpty else {
self.endDateField?.textual content = DateUtil.convertStringFromDate(date: datePickerEnd.date)
return
}
}
personal func validateDate() {
guard let sDate = startDateField?.textual content, !sDate.isEmpty else {
let sRequire = localizedKey(key: "from.require")
self.displayMessage(title: "", message: sRequire, actions: [MessageAction.okAction()])
return
}
guard let eDate = endDateField?.textual content, !eDate.isEmpty else {
let sRequire = localizedKey(key: "to.require")
self.displayMessage(title: "", message: sRequire, actions: [MessageAction.okAction()])
return
}
}
@IBAction func onClickConfirmButton(_ sender: UIButton) {
guard let sDate = startDateField?.textual content, !sDate.isEmpty, let eDate = endDateField?.textual content, !eDate.isEmpty else {
validateDate(); return
}
if startSelectedDate > endSelectedDate {
let invalid = localizedKey(key: "invalid.date")
self.displayMessage(title: "", message: invalid, actions: [MessageAction.okAction()])
return
}
if let val = segementControl?.isSelected, val == true {
if let selectedSegment = segementControl?.selectedSegmentIndex {
confirmDates = dates?[selectedSegment]
}
} else {
guard let startText = startDateField?.textual content, let endText = endDateField?.textual content else {
return
}
let startVal = DateUtil.convert(filledDate: startText, fromFormat: slash, intoFormat: sprint)
let endVal = DateUtil.convert(filledDate: endText, fromFormat: slash, intoFormat: sprint)
confirmDates = Dates(filterId: -1, title: "", begin: startVal, finish: endVal, mobileName: "")
output.dismissView(view: self)
return
}
output.dismissView(view: self)
}
@IBAction func onchangeDateSegment(_ sender: UISegmentedControl) {
self.view.endEditing(true)
segementControl?.isSelected = true
let index = sender.selectedSegmentIndex
if let dateValue = dates?[index] {
startDateField?.textual content = DateUtil.convert(filledDate: dateValue.begin, fromFormat: sprint, intoFormat: slash)
endDateField?.textual content = DateUtil.convert(filledDate: dateValue.finish, fromFormat: sprint, intoFormat: slash)
}
}
personal func localizedKey(key: String) -> String {
return NSLocalizedString(key, tableName: "DateFilter", remark: "")
}
@IBAction func onclickCrossButton(_ sender: UIButton) {
output.dismissView(view: self)
}
personal func setSegmentControlContents(dates: [Dates], confirmDates: Dates?) {
var objects = [String]()
dates.forEach({objects.append($0.mobileName)})
let segmentController = UISegmentedControl(objects: objects)
segmentView?.addSubview(segmentController)
segmentController.addTarget(self, motion: #selector(onchangeDateSegment), for: .valueChanged)
segmentController.autoPinEdge(toSuperviewEdge: .prime)
segmentController.autoPinEdge(toSuperviewEdge: .main)
segmentController.autoPinEdge(toSuperviewEdge: .trailing)
segmentController.autoPinEdge(toSuperviewEdge: .backside)
segmentController.tintColor = UIColor.clear
segmentController.layer.borderColor = UIColor.clear.cgColor
segmentController.setTitleTextAttributes(self.look?.selectedDateFont, for: .chosen)
segmentController.setTitleTextAttributes(self.look?.unSelectedDateFont, for: .regular)
segementControl = segmentController
if dates.accommodates(the place: {$0.mobileName == confirmDates?.mobileName}) {
if let index = dates.firstIndex(the place: {$0.mobileName == confirmDates?.mobileName}) {
segmentController.selectedSegmentIndex = index
segementControl?.isSelected = true
}
}
}
personal func setViewAppearance(look: DateFilterAppearance) {
startDateField?.configureAppearance(look.textAppearance, fieldAppearanceType: .dropDown)
startDateField?.borderedEdges = BorderedEdge.all
startDateField?.delegate = self
startDateField?.placeholder = localizedKey(key: "from")
endDateField?.configureAppearance(look.textAppearance, fieldAppearanceType: .dropDown)
endDateField?.borderedEdges = BorderedEdge.all
endDateField?.delegate = self
endDateField?.placeholder = localizedKey(key: "to")
mainButton?.configureAppearance(look.mainButtonAppearance, title: localizedKey(key: "mainButton.title"))
startLabel?.configureAppearance(look.formLabel)
endLabel?.configureAppearance(look.formLabel)
output.confirmDates = confirmDates
let begin = confirmDates?.begin ?? "", finish = confirmDates?.finish ?? ""
startDateField?.textual content = DateUtil.convert(filledDate: begin, fromFormat: sprint, intoFormat: slash)
endDateField?.textual content = DateUtil.convert(filledDate: finish, fromFormat: sprint, intoFormat: slash)
if let knowledge = dates {
setSegmentControlContents(dates: knowledge, confirmDates: confirmDates)
}
}
@objc func handleStartDatePicker(sender: UIDatePicker) {
segementControl?.isSelected = false
segementControl?.selectedSegmentIndex = -1
startSelectedDate = sender.date
self.startDateField?.textual content = DateUtil.convertStringFromDate(date: sender.date)
}
@objc func handleEndDatePicker(sender: UIDatePicker) {
segementControl?.isSelected = false
segementControl?.selectedSegmentIndex = -1
endSelectedDate = sender.date
self.endDateField?.textual content = DateUtil.convertStringFromDate(date: sender.date)
}
}
extension DateFilterViewController: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
callDatePicker(textField: textField)
}
}
The Difficulty is in beneath movement:
- I’ve chosen startDate as “07/23/24” (i.e twenty third July 2024)
- I’ve chosen endDate as “07/23/24” (i.e. twenty third July 2024)
works tremendous no concern.
then
3. I’ve chosen endDate as “07/24/24” (i.e. twenty fourth July 2024)
It shows Validation Popup as “StartDate can’t be larger than EndDate”
Code :
if startSelectedDate > endSelectedDate {
let invalid = localizedKey(key: "invalid.date")
self.displayMessage(title: "", message: invalid, actions: [MessageAction.okAction()])
return
}
inside onClickConfirmButton
button.
On this case popup shouldn’t be show as It’s setting 07/23/23 on startDate Subject and 07/24/24 on endDate Filed.
The problem is in startSelectedDate and endSelectedDate Values.
I get values as beneath:
startSelectedDate : 2024-10-14 13:51:13 +0000
endSelectedDate : 2024-07-23 18:30:00 +0000