UIPickerView

extension UIPickerView

Delegate and DataSource

UIPickerView closures make it easy to implement UIPickerViewDelegate and UIPickerViewDataSource protocol methods in an organized way. The following is an example of a simple collection view that displays strings in each row.

func loadPickerView() {
    pickerView
        .numberOfRowsInComponent() { _ in
            countries.count
        }.titleForRow() { row, component in
            countries[row]
        }.didSelectRow { row, component in
            log("\(countries[row]) selected")
        }.reloadAllComponents()
}

Arrays

These operations are common. Usually, they involve populating the UIPickerView with the values from an array. Closures framework gives you a convenient way to pass your collection to the table view, so that it can perform the boilerplate operations for you, especially the ones that are required to make the picker view perform at a basic level.

Important

Please remember that Swift Arrays are value types. This means that they are copied when mutaded. When the values or sequence of your array changes, you will need to call one of the add methods again, just before you call reloadData().
func loadPickerView(countries: [String]) {
    let reversed = Array(countries.reversed())
    pickerView
        .addStrings(reversed) { country,component,row in
            log("\(country) selected from array")
        }.reloadAllComponents()
}

Note

Be sure to note that most of the closure callbacks in these array binding methods switch the order of the parameters of row and component. Most of the UIPickerView delegate/datasource method parameters pass row,component. The parameters on the add methods switch the order and send component,row

Multiple Components

And finally, you can just as easily show mutliple components by binding a 2-dimensional array. When using this method, the outer dimension of the array is the component (columns) and the inner dimension are the rows in that component.

let anElement = myTwoDArray[component][row]

In this example, the more verbose row handler is provided just to show the different variations. Adding multiple components has a convenient method to deal with string only arrays also.

func loadPickerView(components: [[String]]) {
    pickerView.addComponents(
        components,
        rowTitle: { country,component,row in
            country},
        didSelect: { country,component,row in
            log("\(country) selected from 2D Array")
    })

    /**
     This also allows you to override any default behavior so
     you aren't overly committed, even though you're initially binding everything
     to the `Array`.
     */
    pickerView.widthForComponent { component in
        component ==  0 ? 200 : 100
    }.reloadAllComponents()
}
  • This method defaults many of the boilerplate callbacks needed to populate a UIPickerView when using an Array as a data source. The defaults that this method takes care of:

    • Provides the number of components
    • Provides the number of rows
    • Handles the pickerView(_:didSelectRow:inComponent:) delegate method
    • Provides the title string for each row

    This method simply sets basic default behavior. This means that you can override the default picker view handlers after this method is called. However, remember that order matters. If you call this method after you override the numberOfComponents callback, for instance, the closure you passed into numberOfComponents will be wiped out by this method and you will have to override that closure handler again.

    Important

    Please remember that Swift Arrays are value types. This means that they are copied when mutaded. When the values or sequence of your array changes, you will need to call this method again, just before you call reloadComponent() or reloadAllComponents(). If you have a lot of picker view customization in addtion to a lot of updates to your array, it is more appropriate to use the individual closure handlers instead of this method.

    An example of calling this method:

    pickerView.addStrings(<#myArray#>) { aTitle,component,row in
        print("\(aTitle) was selected")
    }
    

    Declaration

    Swift

    @discardableResult
    public func addStrings(_ strings: [String],
                           didSelect: @escaping (_ element: String, _ component: Int, _ row: Int) -> Void) -> Self

    Parameters

    strings

    An Array of Strings to be used for each row in a single component picker view.

    didSelect

    A closure that is called when the UIPickerView’s value has been selected.

    Return Value

    itself so you can daisy chain the other delegate/datasource calls

  • This method defaults many of the boilerplate callbacks needed to populate a UIPickerView when using an Array as a data source. The defaults that this method takes care of:

    • Provides the number of components
    • Provides the number of rows
    • Handles the pickerView(_:titleForRow:forComponent:) delegate method
    • Handles the pickerView(_:didSelectRow:inComponent:) delegate method

    This method simply sets basic default behavior. This means that you can override the default picker view handlers after this method is called. However, remember that order matters. If you call this method after you override the numberOfComponents callback, for instance, the closure you passed into numberOfComponents will be wiped out by this method and you will have to override that closure handler again.

    Important

    Please remember that Swift Arrays are value types. This means that they are copied when mutaded. When the values or sequence of your array changes, you will need to call this method again, just before you call reloadComponent() or reloadAllComponents(). If you have a lot of picker view customization in addtion to a lot of updates to your array, it is more appropriate to use the individual closure handlers instead of this method.

    Important

    Be sure to note that most of the closure callbacks in these array binding methods switch the order of the parameters of row and component. Most of the UIPickerView delegate/datasource method parameters have row,component. The handlers’ parameters on the add methods send component,row.


    An example of calling this method:

    pickerView.addElements(
        <#myArray#>,
        rowTitle: { element, component, row in
            return <#aTitle(from: element)#>},
        didSelect: { element, component, row in
            print("\(element) was selected")
    )
    

    Declaration

    Swift

    @discardableResult
    public func addElements<Element>(_ elements: [Element],
                                     rowTitle: @escaping (_ element: Element, _ component: Int, _ row: Int) -> String,
                                     didSelect: @escaping (_ element: Element, _ component: Int, _ row: Int) -> Void) -> Self

    Parameters

    strings

    An Array of any type to be used for each row in a single component picker view.

    rowTitle

    A closure that is called when the UIPickerView needs to display a string for it’s row.

    didSelect

    A closure that is called when the UIPickerView’s value has been selected.

    Return Value

    itself so you can daisy chain the other delegate/datasource calls

  • This method defaults many of the boilerplate callbacks needed to populate a UIPickerView when using an Array as a data source. The defaults that this method takes care of:

    • Provides the number of components
    • Provides the number of rows
    • Handles the pickerView(_:viewForRow:forComponent:) delegate method
    • Handles the pickerView(_:didSelectRow:inComponent:) delegate method

    This method simply sets basic default behavior. This means that you can override the default picker view handlers after this method is called. However, remember that order matters. If you call this method after you override the numberOfComponents callback, for instance, the closure you passed into numberOfComponents will be wiped out by this method and you will have to override that closure handler again.

    Important

    Please remember that Swift Arrays are value types. This means that they are copied when mutaded. When the values or sequence of your array changes, you will need to call this method again, just before you call reloadComponent() or reloadAllComponents(). If you have a lot of picker view customization in addtion to a lot of updates to your array, it is more appropriate to use the individual closure handlers instead of this method.

    Important

    Be sure to note that most of the closure callbacks in these array binding methods switch the order of the parameters of row and component. Most of the UIPickerView delegate/datasource method parameters have row,component. The handlers’ parameters on the add methods send component,row.


    An example of calling this method:

    pickerView.addElements(
        <#myArray#>,
        rowView: { element, reuseView, component, row in
            return <#aView(from: element)#>},
        didSelect: { element, component, row in
            print("\(element) was selected")
    )
    

    Declaration

    Swift

    @discardableResult
    public func addElements<Element>(_ elements: [Element],
                                     rowView: @escaping (_ element: Element, _ reuseView: UIView?, _ component: Int, _ row: Int) -> UIView,
                                     didSelect: @escaping (_ element: Element, _ component: Int, _ row: Int) -> Void) -> Self

    Parameters

    strings

    An Array of any type to be used for each row in a single component picker view.

    rowView

    A closure that is called when the UIPickerView needs to display a view for it’s row.

    didSelect

    A closure that is called when the UIPickerView’s value has been selected.

    Return Value

    itself so you can daisy chain the other delegate/datasource calls

  • This method defaults many of the boilerplate callbacks needed to populate a UIPickerView when using a two-dimensional Array as a data source. The defaults that this method takes care of:

    • Provides the number of components
    • Provides the number of rows
    • Handles the pickerView(_:didSelectRow:inComponent:) delegate method
    • Provides the title string for each row

    This method simply sets basic default behavior. This means that you can override the default picker view handlers after this method is called. However, remember that order matters. If you call this method after you override the numberOfComponents callback, for instance, the closure you passed into numberOfComponents will be wiped out by this method and you will have to override that closure handler again.

    Important

    Please remember that Swift Arrays are value types. This means that they are copied when mutaded. When the values or sequence of your array changes, you will need to call this method again, just before you call reloadComponent() or reloadAllComponents(). If you have a lot of picker view customization in addtion to a lot of updates to your array, it is more appropriate to use the individual closure handlers instead of this method.

    An example of calling this method:

    pickerView.addComponents(<#my2DArray#>) { aTitle,component,row in
        print("\(aTitle) was selected")
    }
    

    Declaration

    Swift

    @discardableResult
    public func addComponents(_ strings: [[String]],
                              didSelect: @escaping (_ element: String, _ component: Int, _ row: Int) -> Void) -> Self

    Parameters

    strings

    An Array of Array of Strings to be used for each row and component in a picker view. The outer dimension of the array is the component (columns) and the inner dimension are the rows in that component. e.g. myTwoDArray[component][row]

    didSelect

    A closure that is called when the UIPickerView’s value has been selected.

    Return Value

    itself so you can daisy chain the other delegate/datasource calls

  • This method defaults many of the boilerplate callbacks needed to populate a UIPickerView when using a two-dimensional Array as a data source. The defaults that this method takes care of:

    • Provides the number of components
    • Provides the number of rows
    • Handles the pickerView(_:titleForRow:forComponent:) delegate method
    • Handles the pickerView(_:didSelectRow:inComponent:) delegate method

    This method simply sets basic default behavior. This means that you can override the default picker view handlers after this method is called. However, remember that order matters. If you call this method after you override the numberOfComponents callback, for instance, the closure you passed into numberOfComponents will be wiped out by this method and you will have to override that closure handler again.

    Important

    Please remember that Swift Arrays are value types. This means that they are copied when mutaded. When the values or sequence of your array changes, you will need to call this method again, just before you call reloadComponent() or reloadAllComponents(). If you have a lot of picker view customization in addtion to a lot of updates to your array, it is more appropriate to use the individual closure handlers instead of this method.

    Important

    Be sure to note that most of the closure callbacks in these array binding methods switch the order of the parameters of row and component. Most of the UIPickerView delegate/datasource method parameters have row,component. The handlers’ parameters on the add methods send component,row.


    An example of calling this method:

    pickerView.addComponents(
        <#my2DArray#>,
        rowTitle: { element, component, row in
            return <#aTitle(from: element, componentIdx: component)#>},
        didSelect: { element, component, row in
            print("\(element) was selected")
    )
    

    Declaration

    Swift

    @discardableResult
    public func addComponents<Element>(_ components: [[Element]],
                                       rowTitle: @escaping (_ element: Element, _ component: Int, _ row: Int) -> String,
                                       didSelect: @escaping (_ element: Element, _ component: Int, _ row: Int) -> Void) -> Self

    Parameters

    components

    An Array of Array of any type to be used for each row and component in a picker view. The outer dimension of the array is the component (columns) and the inner dimension are the rows in that component. e.g. myTwoDArray[component][row]

    rowTitle

    A closure that is called when the UIPickerView needs to display a string for it’s row.

    didSelect

    A closure that is called when the UIPickerView’s value has been selected.

    Return Value

    itself so you can daisy chain the other delegate/datasource calls

  • This method defaults many of the boilerplate callbacks needed to populate a UIPickerView when using a two-dimensional Array as a data source. The defaults that this method takes care of:

    • Provides the number of components
    • Provides the number of rows
    • Handles the pickerView(_:viewForRow:forComponent:) delegate method
    • Handles the pickerView(_:didSelectRow:inComponent:) delegate method

    This method simply sets basic default behavior. This means that you can override the default picker view handlers after this method is called. However, remember that order matters. If you call this method after you override the numberOfComponents callback, for instance, the closure you passed into numberOfComponents will be wiped out by this method and you will have to override that closure handler again.

    Important

    Please remember that Swift Arrays are value types. This means that they are copied when mutaded. When the values or sequence of your array changes, you will need to call this method again, just before you call reloadComponent() or reloadAllComponents(). If you have a lot of picker view customization in addtion to a lot of updates to your array, it is more appropriate to use the individual closure handlers instead of this method.

    Important

    Be sure to note that most of the closure callbacks in these array binding methods switch the order of the parameters of row and component. Most of the UIPickerView delegate/datasource method parameters have row,component. The handlers’ parameters on the add methods send component,row.


    An example of calling this method:

    pickerView.addComponents(
        <#my2DArray#>,
        rowView: { element, reuseView, component, row in
            return <#aView(from: element, componentIdx: component)#>},
        didSelect: { element, component, row in
            print("\(element) was selected")
    )
    

    parameter components: An Array of Array of any type to be used for each row and component in a picker view. The outer dimension of the array is the component (columns) and the inner dimension are the rows in that component. e.g. myTwoDArray[component][row]

    Declaration

    Swift

    @discardableResult
    public func addComponents<Element>(_ components: [[Element]],
                                       rowView: @escaping (_ element: Element, _ reuseView: UIView?, _ component: Int, _ row: Int) -> UIView,
                                       didSelect: @escaping (_ element: Element, _ component: Int, _ row: Int) -> Void) -> Self

    Parameters

    rowView

    A closure that is called when the UIPickerView needs to display a view for it’s row.

    didSelect

    A closure that is called when the UIPickerView’s value has been selected.

    Return Value

    itself so you can daisy chain the other delegate/datasource calls

  • Equivalent to implementing UIPickerViewDelegate’s pickerView(_:rowHeightForComponent:) method

    Declaration

    Swift

    @discardableResult
    public func rowHeightForComponent(handler: @escaping (_ component: Int) -> CGFloat) -> Self

    Parameters

    handler

    The closure that will be called in place of its equivalent delegate method

    Return Value

    itself so you can daisy chain the other delegate calls

  • Equivalent to implementing UIPickerViewDelegate’s pickerView(_:widthForComponent:) method

    Declaration

    Swift

    @discardableResult
    public func widthForComponent(handler: @escaping (_ component: Int) -> CGFloat) -> Self

    Parameters

    handler

    The closure that will be called in place of its equivalent delegate method

    Return Value

    itself so you can daisy chain the other delegate calls

  • Equivalent to implementing UIPickerViewDelegate’s pickerView(_:titleForRow:forComponent:) method

    Declaration

    Swift

    @discardableResult
    public func titleForRow(handler: @escaping (_ row: Int, _ component: Int) -> String?) -> Self

    Parameters

    handler

    The closure that will be called in place of its equivalent delegate method

    Return Value

    itself so you can daisy chain the other delegate calls

  • Equivalent to implementing UIPickerViewDelegate’s pickerView(_:attributedTitleForRow:forComponent:) method

    Declaration

    Swift

    @discardableResult
    public func attributedTitleForRow(handler: @escaping (_ row: Int, _ component: Int) -> NSAttributedString?) -> Self

    Parameters

    handler

    The closure that will be called in place of its equivalent delegate method

    Return Value

    itself so you can daisy chain the other delegate calls

  • Equivalent to implementing UIPickerViewDelegate’s pickerView(_:viewForRow:forComponent:reusing:) method

    Declaration

    Swift

    @discardableResult
    public func viewForRow(handler: @escaping (_ row: Int, _ component: Int, _ reusingView: UIView?) -> UIView) -> Self

    Parameters

    handler

    The closure that will be called in place of its equivalent delegate method

    Return Value

    itself so you can daisy chain the other delegate calls

  • Equivalent to implementing UIPickerViewDelegate’s pickerView(_:didSelectRow:inComponent:) method

    Declaration

    Swift

    @discardableResult
    public func didSelectRow(handler: @escaping (_ row: Int, _ component: Int) -> Void) -> Self

    Parameters

    handler

    The closure that will be called in place of its equivalent delegate method

    Return Value

    itself so you can daisy chain the other delegate calls

  • Equivalent to implementing UIPickerViewDataSource’s numberOfComponents(in:) method

    Declaration

    Swift

    @discardableResult
    public func numberOfComponents(handler: @escaping () -> Int) -> Self

    Parameters

    handler

    The closure that will be called in place of its equivalent dataSource method

    Return Value

    itself so you can daisy chain the other dataSource calls

  • Equivalent to implementing UIPickerViewDataSource’s pickerView(_:numberOfRowsInComponent:) method

    Declaration

    Swift

    @discardableResult
    public func numberOfRowsInComponent(handler: @escaping (_ component: Int) -> Int) -> Self

    Parameters

    handler

    The closure that will be called in place of its equivalent dataSource method

    Return Value

    itself so you can daisy chain the other dataSource calls

  • Clears any delegate/dataSource closures that were assigned to this UIPickerView. This cleans up memory as well as sets the delegate/dataSource properties to nil. This is typically only used for explicit cleanup. You are not required to call this method.

    Declaration

    Swift

    @objc
    public func clearClosureDelegates()