Creating a Custom Picker View - ios

I am trying to create a reusable UIPickerView not unlike UIDatePicker for use in multiple table views. The view works great, but as it's delegate needs to be itself (in order to set the components and rows), I cannot implement the didSelectRow:inComponent: method (to update labels and the model) in the tableViewControllers it is being used in.
How can I subclass UIPickerView and still provide a delegate? If UIDatePicker can do it, I'm guessing there's a pretty straightforward way.

Inspecting the UIDatePicker, it is a subclass of UIControl and follows the target-action pattern. It appears Apple just adds a UIPickerView as a subview to the UIControl. UIDatePicker has made it since the original SDK, so I think I will stick with this method for creating a custom, self-contained PickerView.
More information on custom implementing a custom UIControl: http://www.raywenderlich.com/76433/how-to-make-a-custom-control-swift

Related

What is a proper way for handling actions (events) of the UITableView cell subviews?

I have a UITableView with custom cells. Each cell has a rather complex layout and a lot of child views all of which has event actions: UIImageView with gesture recogniser, several UIButtons with some actions, two UILabels with gesture recognizers.
So I'm interested are there some elegant ways to handle target-action for them?
Now I see three ways:
Handle actions with blocks (BlocksKit to the rescue) right in the cellForRowAtIndexPath:
Create custom class CellEventHandler, pass to it all needed dependencies (controller's navigation controller, data array, etc.) and place all the cell's views action selectors there.
Write all the selectors in the TableViewController (default way)
But I'm not satisfied with all this ways. Can someone describe some elegant way which will help to make controller thin, and also will be easy maintainble. I'm sure there should exist some pattern for this workflow.
Use delegation. When constructing a cell, set it's delegate attribute to some instance that conforms your delegation protocol. When actions are triggered, simply delegate the behavior to the delegate.
That way, you end up with well defined delegation protocol and functionality encapsulated in that class. It is up to you whether the delegate will be e.g. TableViewController or a custom class.
I think the most efficient way to go about handling a complex cells is to subclass UITableViewCell and have all of the events handled directly in the subclass. You can create IBOutlets and inactions directly in there.
In the viewForRowAtIndexPath you can simply call a custom function initWithObject that you can declare in the header of your class so even the initial setup of the cell is out of the viewController greatly simplifying the setup.
The Views and Actions should be in View of MVC pattern that is Custom cell in your case. You should write one method for gestureRecognizer(tapGestureRecognizer added on your cell) in your custom cell class. Method will identify the type of object which invoke it through introspection i.e. isKindOfClass UIButton/ Label / ImageView. Each object will further identify with its tag like if gestureRecognizer say it is label which invoke this method but which label label1 or label2 now you can compare its tag to detect it.

Get selected value from UIPickerView custom delegate & data source

So I cannot provide you with any code, but it's quite simple what I want to achieve.
I am searching for a way to get the selected value from an UIPickerView in iOS 8 (Swift)
these pickerviews have a custom delegate & data source.
So the method of didSelectRow is accessed in a custom class, not the ViewController, but I would have to be able to get the selected value and use it in the ViewController. Let's say, place it in a textbox.
I can't find a way to do this, should I try to access the delegate itself or what should I be doing?
Care to share your knowledge with the students of Application Development? :)
The UIPickerView class has a method named: `selectedRowInComponent'. This function may help you select components in a picker view. Apple Documentation for UIPickerView class would help you with your project.
Also make sure your view controller conforms to the UIPickerViewController Delegate and Data source.

Same UIPickerView in different ViewControllers

I'm new to objective-c and iOS app development, and I have next question:
Is it possible to have one picker view in different views, I mean it should have same data in it and behave equally. Currently i have added 3 picker views, each in different view, and now i have triple copy of same code. So to avoid code duplicating, is there way to create custom view and put this in each of 3 view controllers and just initialize it. Thanks.
Sure. You could even do it all from a separate NSObject inherited class.
Then make that picker class handle all of the picker stuff via its methods.
Then the view controller that wants to use it only has to have an instance of this picker object and it directly calls the needed methods.
That or you can directly create an UIPickerView inherited object and automatically setup its data when it's initialized and use that instead of UIPickerView.
Some quick example code can be found by googling. Here's one: http://iphonedevsdk.com/forum/iphone-sdk-development/46378-subclassing-uipickerview-question.html

Appropriate way to add multiple UIPicker controls on page

iOS Proficiency: Beginner
If I have a Xib with multiple fields that all need their own Picker View, what's an appropriate/canonical way to add multiple picker views on the page without getting the Design View all cluttered up?
1) Only add the PickerView programmatically and not via the XIB?
2) Use only 1 Picker object and populate it with different values based on the field
selection? (Possible memory benefits?)
3) Place the UIPickers on the View with a tiny height/width and then programmatically adjust height when necessary? Not even sure if the height is adjustable.
4)Combination of some of the above?
You can see in the image below, how cluttered it looks already even with just one picker view:
The view that you have with the text fields and picker views would lend itself to be part of a UITableView.
See the calendar app when you add an event.
You can set this up fairly easily by using a static UITableView.
I'm replying on my phone at the moment but will look for a tutorial if you would like.
If only one pickerView will be visible at once, then you should consider using only one pickerView and configure it's delegate/datasource so that you can give it a different datasource for each field.
Unless more than one is visible at once, there really isn't any reason to use more than one in your nib file. And even if you used more than one, you would still have to configure you delegate/datasource methods to handle each individual picker.
Hope that helps.
EDIT: It would be a little bit of work, but if you wanted the pickerView to animate in and out of the view whenever you need and if you wanted to clean your Xib up even more you could do the following:
Create a subview containing your pickerView
Set up a protocol on the subview to allow you to pass the selected value back to the view controller.
Set up your viewController to conform to the protocol on your picker subview.
Set the pickerView to be each textField's inputView.
Set the textField's delegate methods to configure the dataSource of your subview when editing begins.
By doing this, you have set your textField so that when it receives firstResponder that it will display the pickerView instead of a keyboard.

Using to different delegate method for the same picker?

Im trying to create a view with two pickers, each with multiple components, one of the pickers has 4 components that are all text based, the other has two components that need to display graphics and two that need to display text. Is there any way to use the pickerView:titleForRow:forComponent:(NSInteger)component delegate method and the pickerView:viewForRow:forComponent:reusingView: delegate method for the same picker?
I've implemented both, only the viewForRow one seems to ever get called. Do I need to just use that one and create a view with a label for each row?
You can create one picker, yes, or you can implement one common method for both pickers and determine what picker is calling it by checking it's tag.
The Solution I cam up with was to call pickerView:titleForRow:forComponent: from pickerView:viewForRow:forComponent:reusingView: and create a UILabel with the string from the first method. It works, but it seems like there ought to be a better way.

Resources