Instantly share code, notes, and snippets.

Embed
What would you like to do?
Swift Generic UIPickerView
class PickerSource : NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
var data: [[String]] = []
var selectionUpdated: ((component: Int, row: Int) -> Void)?
// MARK: UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return data.count
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
let rows = data[component]
return rows.count
}
// MARK: UIPickerViewDelegate
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return "\(data[component][row])"
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectionUpdated?(component: component, row: row)
}
}
class Picker<T : Printable> : UIPickerView {
var data: [[T]] = [] {
didSet {
source.data = data.map { $0.map { "\($0)" } }
reloadAllComponents()
}
}
var selectionUpdated: ((selections: [T?]) -> Void)?
private let source = PickerSource()
// MARK: Initialization
convenience init() {
self.init(frame: CGRectZero)
}
convenience init(data: [[T]]) {
self.init(frame: CGRectZero)
self.data = data
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
// MARK: Setup
private func setup() {
dataSource = source
delegate = source
source.selectionUpdated = { [weak self] component, row in
if let _self = self {
var selections: [T?] = []
for (idx, componentData) in enumerate(_self.data) {
let selectedRow = _self.selectedRowInComponent(idx)
if selectedRow >= 0 {
selections.append(componentData[selectedRow])
} else {
selections.append(nil)
}
}
_self.selectionUpdated?(selections: selections)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment