DatePickerRow.swift 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // DateRow.swift
  2. // Eureka ( https://github.com/xmartlabs/Eureka )
  3. //
  4. // Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )
  5. //
  6. //
  7. // Permission is hereby granted, free of charge, to any person obtaining a copy
  8. // of this software and associated documentation files (the "Software"), to deal
  9. // in the Software without restriction, including without limitation the rights
  10. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. // copies of the Software, and to permit persons to whom the Software is
  12. // furnished to do so, subject to the following conditions:
  13. //
  14. // The above copyright notice and this permission notice shall be included in
  15. // all copies or substantial portions of the Software.
  16. //
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. // THE SOFTWARE.
  24. import Foundation
  25. import UIKit
  26. open class DatePickerCell: Cell<Date>, CellType {
  27. @IBOutlet weak public var datePicker: UIDatePicker!
  28. public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  29. let datePicker = UIDatePicker()
  30. self.datePicker = datePicker
  31. self.datePicker.translatesAutoresizingMaskIntoConstraints = false
  32. super.init(style: style, reuseIdentifier: reuseIdentifier)
  33. self.contentView.addSubview(self.datePicker)
  34. self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[picker]-0-|", options: [], metrics: nil, views: ["picker": self.datePicker!]))
  35. self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[picker]-0-|", options: [], metrics: nil, views: ["picker": self.datePicker!]))
  36. }
  37. required public init?(coder aDecoder: NSCoder) {
  38. super.init(coder: aDecoder)
  39. }
  40. open override func setup() {
  41. super.setup()
  42. selectionStyle = .none
  43. accessoryType = .none
  44. editingAccessoryType = .none
  45. height = { UITableView.automaticDimension }
  46. datePicker.datePickerMode = datePickerMode()
  47. datePicker.addTarget(self, action: #selector(DatePickerCell.datePickerValueChanged(_:)), for: .valueChanged)
  48. }
  49. deinit {
  50. datePicker?.removeTarget(self, action: nil, for: .allEvents)
  51. }
  52. open override func update() {
  53. super.update()
  54. selectionStyle = row.isDisabled ? .none : .default
  55. datePicker.isUserInteractionEnabled = !row.isDisabled
  56. detailTextLabel?.text = nil
  57. textLabel?.text = nil
  58. datePicker.setDate(row.value ?? Date(), animated: row is CountDownPickerRow)
  59. datePicker.minimumDate = (row as? DatePickerRowProtocol)?.minimumDate
  60. datePicker.maximumDate = (row as? DatePickerRowProtocol)?.maximumDate
  61. if let minuteIntervalValue = (row as? DatePickerRowProtocol)?.minuteInterval {
  62. datePicker.minuteInterval = minuteIntervalValue
  63. }
  64. }
  65. @objc func datePickerValueChanged(_ sender: UIDatePicker) {
  66. row?.value = sender.date
  67. // workaround for UIDatePicker bug when it doesn't trigger "value changed" event after trying to pick 00:00 value
  68. // for details see this comment: https://stackoverflow.com/questions/20181980/uidatepicker-bug-uicontroleventvaluechanged-after-hitting-minimum-internal#comment56681891_20204225
  69. if sender.datePickerMode == .countDownTimer && sender.countDownDuration == TimeInterval(sender.minuteInterval * 60) {
  70. datePicker.countDownDuration = sender.countDownDuration
  71. }
  72. }
  73. private func datePickerMode() -> UIDatePicker.Mode {
  74. switch row {
  75. case is DatePickerRow:
  76. return .date
  77. case is TimePickerRow:
  78. return .time
  79. case is DateTimePickerRow:
  80. return .dateAndTime
  81. case is CountDownPickerRow:
  82. return .countDownTimer
  83. default:
  84. return .date
  85. }
  86. }
  87. }
  88. open class _DatePickerRow: Row<DatePickerCell>, DatePickerRowProtocol {
  89. open var minimumDate: Date?
  90. open var maximumDate: Date?
  91. open var minuteInterval: Int?
  92. required public init(tag: String?) {
  93. super.init(tag: tag)
  94. displayValueFor = nil
  95. }
  96. }
  97. /// A row with an Date as value where the user can select a date directly.
  98. public final class DatePickerRow: _DatePickerRow, RowType {
  99. public required init(tag: String?) {
  100. super.init(tag: tag)
  101. }
  102. }
  103. /// A row with an Date as value where the user can select a time directly.
  104. public final class TimePickerRow: _DatePickerRow, RowType {
  105. public required init(tag: String?) {
  106. super.init(tag: tag)
  107. }
  108. }
  109. /// A row with an Date as value where the user can select date and time directly.
  110. public final class DateTimePickerRow: _DatePickerRow, RowType {
  111. public required init(tag: String?) {
  112. super.init(tag: tag)
  113. }
  114. }
  115. /// A row with an Date as value where the user can select hour and minute as a countdown timer.
  116. public final class CountDownPickerRow: _DatePickerRow, RowType {
  117. public required init(tag: String?) {
  118. super.init(tag: tag)
  119. }
  120. }