I\'m looking for a way to present a UIPickerView
when the user taps on a UIBarButtonItem
. Imagine a filter for the table view results.
I know I
I went with borisgolovnev's suggestion of an invisible UITextField
and came up with the following Swift 2.3 implementation:
import UIKit
class PickerViewPresenter: UITextField {
// MARK: - Initialization
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init() {
super.init(frame: CGRect.zero)
inputView = pickerView
inputAccessoryView = pickerInputAccessoryView
}
// MARK: - Public
var pickerDelegate: UIPickerViewDelegate? {
didSet {
pickerView.delegate = pickerDelegate
}
}
var pickerDataSource: UIPickerViewDataSource? {
didSet {
pickerView.dataSource = pickerDataSource
}
}
var selectButtonAction: (() -> Void)?
var currentlySelectedRow: Int {
return pickerView.selectedRowInComponent(0)
}
func selectRowAtIndex(index: Int) {
pickerView.selectRow(index, inComponent: 0, animated: false)
}
func showPicker() {
self.becomeFirstResponder()
}
func hidePicker() {
self.resignFirstResponder()
}
// MARK: - Views
private let pickerView = UIPickerView(frame: CGRect.zero)
private lazy var pickerInputAccessoryView: UIView = {
let frame = CGRect(x: 0.0, y: 0.0, width: 0.0, height: 48.0)
let pickerInputAccessoryView = UIView(frame: frame)
// Customize the view here
return pickerInputAccessoryView
}()
func selectButtonPressed(sender: UIButton) {
selectButtonAction?()
}
}
PickerViewPresenter can then conveniently be used as such:
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(pickerViewPresenter)
}
private let dataModel = [10, 20, 30, 40, 50]
private lazy var pickerViewPresenter: PickerViewPresenter = {
let pickerViewPresenter = PickerViewPresenter()
pickerViewPresenter.pickerDelegate = self
pickerViewPresenter.pickerDataSource = self
pickerViewPresenter.selectButtonAction = { [weak self] () -> Void in
guard let strongSelf = self else {
return
}
let result = strongSelf.dataModel[pickerViewPresenter.currentlySelectedRow]
pickerViewPresenter.hidePicker()
// ...
}
return pickerViewPresenter
}()
private func presentPickerView {
let index = 0 // [0..dataModel.count-1]
pickerViewPresenter.selectRowAtIndex(index)
pickerViewPresenter.showPicker()
}
// MARK: - UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return dataModel.count
}
// MARK: - UIPickerViewDelegate
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return "\(dataModel[row]) drunken sailors"
}
}
Hope someone finds this useful =)