iOS 14 新增 UIDatePicker 的使用及向下兼容

发布
更新
字数 279
阅读 2 分钟
阅读量 915

新的 UIDatePicker 可以作为 inline 的输入控件直接使用,为了向下兼容,可以在 iOS 低版本时提供一个 UITextField 作为默认的输入控件,或 UILabel 仅用来显示。

例如在一个 UITableViewCell 中:

// 在低版本作为输入显示控件,即用户轻触 textField 会显示一个 datePicker 作为输入视图
fileprivate(set) lazy var textField: UITextField = {
    let textField = UITextField()
    contentView.addSubview(textField)
    textField.backgroundColor = .red

    textField.translatesAutoresizingMaskIntoConstraints = false
    let margins = contentView.layoutMarginsGuide
    NSLayoutConstraint.activate([
        textField.centerYAnchor.constraint(equalTo: margins.centerYAnchor, constant: yOffset),
        textField.trailingAnchor.constraint(equalTo: margins.trailingAnchor),
        textField.leadingAnchor.constraint(greaterThanOrEqualTo: detailLabel.trailingAnchor, constant: .tertiaryPadding),
    ])

    return textField
}()

fileprivate(set) lazy var datePicker: UIDatePicker = {
    let datePicker = UIDatePicker()
    datePicker.datePickerMode = .time

    // 兼容性
    if #available(iOS 14.0.0, *) {
        // iOS 14 之后直接替代 textField 显示
        datePicker.preferredDatePickerStyle = .inline
        datePicker.translatesAutoresizingMaskIntoConstraints = false

        contentView.addSubview(datePicker)

        let margins = contentView.layoutMarginsGuide
        NSLayoutConstraint.activate([
            datePicker.centerYAnchor.constraint(equalTo: margins.centerYAnchor, constant: yOffset),
            datePicker.trailingAnchor.constraint(equalTo: margins.trailingAnchor),
            datePicker.leadingAnchor.constraint(greaterThanOrEqualTo: detailLabel.trailingAnchor, constant: .tertiaryPadding),
        ])
    } else {
        // 较低版本,设置 datePicker 作为 textField 的输入视图
        textField.inputView = datePicker
    }

    return datePicker
}()

使用时,例如在控制器中,可以根据 iOS 版本判断:

guard let reminderTimeCell = cell as? ScheduleConfigureReminderTimeCell else { return }

reminderTimeCell.datePicker.date = schedule.expectedTriggerDate
reminderTimeCell.datePicker.addTarget(self, action: #selector(handleReminderTimeChanged(_:)), for: .valueChanged)

guard #available(iOS 14.0.0, *) else {
    // less than iOS 14
    reminderTimeCell.textField.text = schedule.expectedTriggerDate.localizedShortTime
    return
}