我认为您最好的解决方案是简单地使用普通的UIPickerView。这样你几乎可以控制一切。作为演示,我创建了这个全代码示例,它几乎可以满足您的需求:
class ViewController: UIViewController {
private let pickerView: UIPickerView = UIPickerView(frame: CGRect(x: 0.0, y: 300.0, width: 100.0, height: 300.0))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(pickerView)
pickerView.dataSource = self
pickerView.delegate = self
pickerView.reloadAllComponents()
pickerView.selectRow(50000, inComponent: 0, animated: false)
pickerView.selectRow(50000, inComponent: 1, animated: false)
view.addSubview({
let label = UILabel(frame: .zero)
label.text = ":"
label.sizeToFit()
label.center = pickerView.center
label.isUserInteractionEnabled = false
return label
}())
}
}
extension ViewController: UIPickerViewDataSource, UIPickerViewDelegate {
private func hourValueAtIndex(index: Int) -> Int {
return index%12
}
private func minuteValueAtIndex(index: Int) -> Int {
return index%60
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 100000
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch component {
case 0: return String(hourValueAtIndex(index: row))
case 1: return String(minuteValueAtIndex(index: row))
default: return ""
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let calendarToUse = Calendar.autoupdatingCurrent
var components = calendarToUse.dateComponents([.year, .month, .day], from: Date())
components.hour = hourValueAtIndex(index: pickerView.selectedRow(inComponent: 0))
components.minute = minuteValueAtIndex(index: pickerView.selectedRow(inComponent: 1))
let selectedDate = calendarToUse.date(from: components)
print("Selected new time (in UTC): \(selectedDate!)")
let formatter = DateFormatter()
formatter.calendar = calendarToUse
formatter.dateStyle = .short
formatter.timeStyle = .short
print("Selected new time (local): \(formatter.string(from: selectedDate!))")
}
}
如果需要,我会将所有这些都放在故事板甚至 xib 中以使其可重用。结肠的定位和样式可能需要一些工作,但这取决于您想要什么设计。我只是为组件使用了 100k 值来模拟无限滚动。至少应该为此定义一些常量。
通知hourValueAtIndex和minuteValueAtIndex;这些可以被操纵以使用几乎任何你需要的东西。要让它在 0-23 小时内运行,您只需使用 index%24。不过,要拥有它1-24 需要做更多的工作:您将返回index%24 + 1,但在构造日期时,您需要将 24 的值作为异常处理。您将使用 0 并添加额外的一天。但是您不能直接向组件添加额外的一天,因为您可能会在 7 月 32 日这样的情况下溢出。您确实需要在末尾添加一天:
selectedDate = calendarToUse.date(byAdding: DateComponents(day: 1), to: selectedDate)