Swift:如何制作显示日期和时间范围的uipickerview

时间:2018-08-29 15:39:10

标签: ios swift uipickerview

我可以显示时间并更改时间间隔,但是除非我对它进行硬编码,否则我不知道如何获得一个日期如下图所示的时间范围。 尽量避免使用任何椰子足。现在,我很难对它进行编码,但只有时间,如果没有另一个UIPicker,我将无法获得日期。

与所讨论的UIPickerView相关的代码:

private var deliveryTimesPicker = UIPickerView()
private var deliveryTimes = ["10 AM - 11 AM", "11 AM - 12 PM", "12 PM - 1 PM", "1 PM - 2 PM", "2 PM - 3 PM", "3 PM - 4 PM", "4 PM - 5 PM", "5 PM - 6 PM", "6 PM - 7 PM", "7 PM - 8 PM", "8 PM - 9 PM", "9 PM - 10 PM", "10 PM - 11 PM"]
private var selectedDeliveryTime = 0

override func viewDidLoad() {
    ...
    self.deliveryTimeTF.text = self.deliveryTimes.first!

    self.doneToolbar.barStyle = .default
    self.doneToolbar.isTranslucent = true
    self.doneToolbar.isUserInteractionEnabled = true
    self.doneToolbar.setItems([
        UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(self.dismissKeyboard)),
        UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
        UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.pickerViewDone))
        ], animated: true)
    self.doneToolbar.sizeToFit()

    self.deliveryTimesPicker.delegate = self
    self.deliveryTimesPicker.dataSource = self
    self.deliveryTimesPicker.tag = 0
    self.deliveryTimesPicker.selectRow(self.selectedDeliveryTime, inComponent: 0, animated: true)
    self.deliveryTimeTF.inputView = self.deliveryTimesPicker
    self.deliveryTimeTF.inputAccessoryView = self.doneToolbar
}


@objc func pickerViewDone() {
    if self.deliveryTimeTF.isEditing {
        self.deliveryTimeTF.text = self.deliveryTimes[self.selectedDeliveryTime]
    }
    dismissKeyboard()
}

extension RequestViewController: UIPickerViewDelegate {
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if pickerView.tag == 0 {
            self.selectedDeliveryTime = row
            return self.deliveryTimes[self.selectedDeliveryTime]
        }
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if pickerView.tag == 0 {
             self.selectedDeliveryTime = row
        }
    }

}

我的情况如何

enter image description here

我想要的样子(颜色主题不仅仅是它的功能并不重要): From skipthedishes app

3 个答案:

答案 0 :(得分:0)

  

除非我对它进行硬编码,否则我不知道如何获得带有下图所示日期的时间表。

然后,您应该阅读DateDateIntervalDateComponents等。选择一个开始日期,并使用它生成一对开始日期和结束日期。这是一些伪代码:

let start = Date()
var timeframes = (Date,Date)[]
for i in (0..9) {
    let t1 = Date(timeInterval: (i * secondsBetweenStarts) since:start)
    let t2 = Date(timeInterval: timeFrameDuration since:t1)
    let timeframe = (t1, t2)
    timeframes.append(timeframe)
}

您当然必须填写secondsBetweenStartstimeFrameDuration的值。还有许多其他构造日期的方法-例如,使用日期组件将使创建以小时为界的开始和结束期间变得容易。无论如何,这个想法只是创建一个开始时间和结束时间的数组。从那里很容易生成描述这些时间范围的字符串列表,您可以在选择器中使用该字符串列表。

答案 1 :(得分:0)

始终避免使用标签来识别事物,选择器将是正确的选择。

此方法返回选择器上的两个项目供用户选择,您只需要用您希望它开始的时间来调整第一个日期。用户将能够选择交货日期和交货时间,当选择器值更改时,代码将为您提供带有交货时间范围的选定日期,您还可以使用选择器在pickerViewDone函数上使用didSelectRow上的逻辑。 var(deliveryTimesPicker)作为来源。

我唯一没有做的就是检查optionals值,还需要确保选择器至少具有两个组件(picker.numberOfComponents),并且日期是否正确生成。

let deliveryDateDayFormatter = DateFormatter()
let deliveryDateTimeFormatter = DateFormatter()

let deliveryDateDays: [String] = {
    deliveryDateDayFormatter.dateFormat = "E, d MMM y"
    deliveryDateTimeFormatter.dateFormat = "h:mm a"

    var deliveryDate = Date()
    var deliveryDateDaysArray: [String] = []
    deliveryDateDaysArray.append("Today")

    for dateIndex in 0 ... 8 {
        deliveryDate = Calendar.current.date(byAdding: .day, value: dateIndex, to: deliveryDate)!

        let deliveryDateDay = deliveryDateDayFormatter.string(from: deliveryDate)

        deliveryDateDaysArray.append("\(deliveryDateDay)")
    }
    return deliveryDateDaysArray
}()


let deliveryDateTimes: [String] = {
    deliveryDateDayFormatter.dateFormat = "E, d MMM y"
    deliveryDateTimeFormatter.dateFormat = "h:mm a"

    var deliveryDate = Date()
    var deliveryDateTimesArray: [String] = []
    deliveryDateTimesArray.append("ASAP")

    for _ in 0 ... 8 {
        let deliveryDateTimeFrom = deliveryDateTimeFormatter.string(from: deliveryDate)

        deliveryDate = Calendar.current.date(byAdding: .minute, value: 30, to: deliveryDate)!

        let deliveryDateTimeTo = deliveryDateTimeFormatter.string(from: deliveryDate)

        deliveryDateTimesArray.append("\(deliveryDateTimeFrom) - \(deliveryDateTimeTo)")
    }
    return deliveryDateTimesArray
}()

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

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    var pickerComponents: [[String]] = []

    pickerComponents.append(deliveryDateDays)
    pickerComponents.append(deliveryDateTimes)

    return pickerComponents[component].count
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "E, d MMM y h:mm a"

    let selectedDeliveryDayIndex = pickerView.selectedRow(inComponent: 0)
    let selectedDeliveryTimeIndex = pickerView.selectedRow(inComponent: 1)

    let selectedDeliveryDay = deliveryDateDays[selectedDeliveryDayIndex]
    let selectedDeliveryTime = deliveryDateTimes[selectedDeliveryTimeIndex]

    let fullTimeRange = selectedDeliveryTime.components(separatedBy: " - ")

    let timeFrom   = fullTimeRange[0]
    let timeTo = fullTimeRange[1]

    let selectedDateStringFrom = "\(selectedDeliveryDay) \(timeFrom)"
    let selectedDateStringTo = "\(selectedDeliveryDay) \(timeTo)"

    //Delivery date from
    let selectedDateTimeFrom = dateFormatter.date(from: selectedDateStringFrom)!

    //Delivery date to
    let selectedDateTimeTo = dateFormatter.date(from: selectedDateStringTo)!

    //Delivery range
    var deliveryDate = (selectedDateTimeFrom,selectedDateTimeTo)

    print(selectedDateTimeFrom)
    print(selectedDateTimeTo)

    print(deliveryDateDays)
    print(deliveryDateTimes)
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    var pickerComponents: [[String]] = []

    pickerComponents.append(deliveryDateDays)
    pickerComponents.append(deliveryDateTimes)

    return pickerComponents[component][row]
}

答案 2 :(得分:-1)

根据您的代码,您可以使用如下键盘视图:

protocol DeliveryTimeKeyboardDelegate  {
    func closeKeyboard()
    func validate(deliveryTime: (Date, Int)?)
}

class DeliveryTimeKeyboard: UIStackView {
    let datePickerView = UIDatePicker()
    let hourPickerView = UIPickerView()
    var delegate: DeliveryTimeKeyboardDelegate?
    private var deliveryTimes = ["10 AM - 11 AM", "11 AM - 12 PM", "12 PM - 1 PM", "1 PM - 2 PM", "2 PM - 3 PM", "3 PM - 4 PM", "4 PM - 5 PM", "5 PM - 6 PM", "6 PM - 7 PM", "7 PM - 8 PM", "8 PM - 9 PM", "9 PM - 10 PM", "10 PM - 11 PM"]

    var cancelButton: UIBarButtonItem?
    var clearButton: UIBarButtonItem?
    var doneButton: UIBarButtonItem?

    var deliveryTime: (Date, Int) {
        let day = datePickerView.date
        let period = hourPickerView.selectedRow(inComponent: 0)
        return (day, period)
    }

    var toolbar: UIToolbar {
        let toolBar = UIToolbar()

        toolBar.barStyle = UIBarStyle.default
        toolBar.isTranslucent = true
        toolBar.tintColor = UIColor.black
        toolBar.sizeToFit()

        let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.cancelAction))
        let clearButton = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(self.clearAction))
        let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.doneAction))
        let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
        self.cancelButton = cancelButton
        self.clearButton = clearButton
        self.doneButton = doneButton

        toolBar.setItems([cancelButton, spaceButton, clearButton, spaceButton, doneButton], animated: false)
        toolBar.isUserInteractionEnabled = true
        return toolBar
    }

    convenience init() {
        self.init(frame:  CGRect(x: 0, y: 0, width: 1, height: 216))
        addArrangedSubview(datePickerView)
        addArrangedSubview(hourPickerView)
        datePickerView.datePickerMode = .date
        hourPickerView.delegate = self
        hourPickerView.dataSource = self

        axis = .horizontal
    }


    @objc func cancelAction() {
        delegate?.closeKeyboard()
    }

    @objc func clearAction() {
        delegate?.validate(deliveryTime: nil)
    }

    @objc func doneAction() {
        delegate?.validate(deliveryTime: deliveryTime)
    }
}

extension DeliveryTimeKeyboard: UIPickerViewDelegate {
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        guard row < deliveryTimes.count else { return nil }
        return deliveryTimes[row]
    }
}
extension DeliveryTimeKeyboard: UIPickerViewDataSource {
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return deliveryTimes.count
    }
}

class ViewController: UIViewController {

    @IBOutlet weak var inputDeliveryTime: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        let deliveryTimeKeyboard = DeliveryTimeKeyboard()
        inputDeliveryTime.inputView = deliveryTimeKeyboard
        inputDeliveryTime.inputAccessoryView = deliveryTimeKeyboard.toolbar
    }
}