是否可以让 UIDatePicker 使用开始时间和结束时间?

Is it possible to have UIDatePicker work with start and end time?

目前我有一个像下面这样工作的 UIDatePicker:

但我想让它像下面那样使用开始和结束时间?

有人在 UIDatePicker 上完成过这个定制吗?

这样使用UIDatePicker的应用是https://www.zeel.com/

谢谢!

这是一篇关于设计 UIPickerView 的博客,它几乎完全符合您在屏幕截图中显示的内容:

http://codewithchris.com/uipickerview-example/

您只需编辑选择器视图中显示的数据即可。

您必须创建自己的 UIPickerView 并创建自己的列和行。这可以通过将 UIPickerView 拖到 UIViewController 并将其设置为 UIPickerViewdataSourcedelegate 来完成。实现 dataSourcedelegate 协议方法:

class PickerViewController : UIViewController, UIPickerViewDelegate, UIPickerViewDataSource{

     func numberOfComponents(in pickerView: UIPickerView) -> Int {

          return numberOfColumns
     }


    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

          return rowsInEachColumn
     }

     func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

        //set title for each row here depending on component   
     }

     //or if you want to customize the view of each row,
     //func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {

     //}
}

dataSourcedelegates类似于UITableView。您的 numberOfComponents 表现得像部分,而 numberOfRowsInComponent 表现得像部分中的行。如您所料,您将有一个委托方法来告诉您用户选择了哪一行。

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

}

虽然 Rikn 和 Kayla 的回答为我指明了正确的方向,但他们没有像我在问题中提供的图像中那样获取日期的部分,所以这就是为什么我将代码放在这里的原因做到了。

结果:

代码:

属性

class ViewController: UIViewController {
  @IBOutlet weak var pickerView: UIPickerView!
  
  var days = [Date]()
  var startTimes = [Date]()
  var endTimes = [Date]()
  
  let dayFormatter = DateFormatter()
  let timeFormatter = DateFormatter()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    dayFormatter.dateFormat = "EE d MMM"
    timeFormatter.timeStyle = .short

    days = setDays()
    startTimes = setStartTimes()
    endTimes = setEndTimes()
  }
}

辅助方法

extension ViewController {
  func getDays(of date: Date) -> [Date] {
    var dates = [Date]()
    
    let calendar = Calendar.current
    
    // first date
    var currentDate = date
    
    // adding 30 days to current date
    let oneMonthFromNow = calendar.date(byAdding: .day, value: 30, to: currentDate)
    
    // last date
    let endDate = oneMonthFromNow
    
    while currentDate <= endDate! {
      dates.append(currentDate)
      currentDate = calendar.date(byAdding: .day, value: 1, to: currentDate)!
    }
    
    return dates
  }
  
  func getTimes(of date: Date) -> [Date] {
    var times = [Date]()
    var currentDate = date
    
    currentDate = Calendar.current.date(bySetting: .hour, value: 7, of: currentDate)!
    currentDate = Calendar.current.date(bySetting: .minute, value: 00, of: currentDate)!
    
    let calendar = Calendar.current
    
    let interval = 60
    var nextDiff = interval - calendar.component(.minute, from: currentDate) % interval
    var nextDate = calendar.date(byAdding: .minute, value: nextDiff, to: currentDate) ?? Date()
    
    var hour = Calendar.current.component(.hour, from: nextDate)
    
    while(hour < 23) {
      times.append(nextDate)
      
      nextDiff = interval - calendar.component(.minute, from: nextDate) % interval
      nextDate = calendar.date(byAdding: .minute, value: nextDiff, to: nextDate) ?? Date()
      
      hour = Calendar.current.component(.hour, from: nextDate)
    }
    
    return times
  }
  
  func setDays() -> [Date] {
    let today = Date()
    return getDays(of: today)
  }
  
  func setStartTimes() -> [Date] {
    let today = Date()
    return getTimes(of: today)
  }
  
  func setEndTimes() -> [Date] {
    let today = Date()
    return getTimes(of: today)
  }
  
  func getDayString(from: Date) -> String {
    return dayFormatter.string(from: from)
  }
  
  func getTimeString(from: Date) -> String {
    return timeFormatter.string(from: from)
  }
}

选取器委托

extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
  func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 3
  }
  
  func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    switch component {
    case 0:
      return days.count
    case 1:
      return startTimes.count
    case 2:
      return endTimes.count
    default:
      return 0
    }
  }
  
  func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
    var label: UILabel
    
    if let view = view as? UILabel {
      label = view
    } else {
      label = UILabel()
    }
    
    label.textColor = .black
    label.textAlignment = .center
    label.font = UIFont.systemFont(ofSize: 15)
    
    var text = ""
    
    switch component {
    case 0:
      text = getDayString(from: days[row])
    case 1:
      text = getTimeString(from: startTimes[row])
    case 2:
      text = getTimeString(from: endTimes[row])
    default:
      break
    }
    
    label.text = text
    
    return label
  }
}