I am trying to build a custom UIPickerView
replacement class mainly for learning purposes but with a view to implementing this within an application I am developing. I have put a lot of time and effort into the UI of my application and now the default UIPickerView
just doesn't fit right.
I saw this Dribble mock up of a really slick looking date/time picker but realise that theres not a chance in hell that UIPickerView
can be customised this heavily without some major hacking.
After a whole lot of reading and investigation, I have found that UIPickerView
uses UITableView
s for it's components rather than a plain UIScrollView
as I had first assumed. This is confusing for two reasons:
Customising UITableViewCell
s is a major pain in the derriere. It's not that it's hard work, just laborious and rarely yields the required result. Somehow UIPickerView
manages to pull this off though with very little overhead. I would assume that each row in a component just uses UITableViewCellStyleDefault
with a custom view for it's contentView
but you know what they say about assumptions.
The second thing that is throwing me off is that UIPickerView
conforms to the UITableViewDataSource
protocol, but not the UITableViewDelegate
protocol. This seems a little odd as the delegate is responsible for providing the correct height via – tableView:heightForRowAtIndexPath:
UIPickerView
however does allow you to set the size of a component via – pickerView:rowHeightForComponent:
In line with this, it also seems a strange choice to utilise a table view as natively these do not "snap" to a specified row the way a scroll view would with pagingEnabled
.
Can anyone offer up an explanation of why the default UIPickerView
doesn't conform to the aforementioned delegate? Would it be easier for me to implement my custom picker with a UIScrollView
instead or should the UITableView
provide the functionality required?
UIPickerView
actually conforms to UITableViewDelegate
protocol but just does not expose that in public headers. You can check that yourself using class_copyProtocolList
function.
Using UITableView internally makes it much easier to implement pickers with large amount of rows as UITableView provides great support for reusing cells, otherwise Apple would need to reimplement that logic once again for picker - that would not make much sense (sorry I don't see any big problems in customizing UITableViewCell for this case, so it is hard to comment on that)
As UITableView is UIScrollView subclass you can make it "snap" to a specific position, check scrollViewWillEndDragging:withVelocity:targetContentOffset:
method in UIScrollViewDelegate
protocol that can be used for exactly that purpose.