How to handle UIPickerView with two data sources? - iphone

is it possible to handle two data sources in the UIPickerView?
I have here a segmented control that would control the display of the picker view.
So, for example, when first segment is clicked, the picker will display person's name. Then, when second segment is clicked, picker will display place's name.
Thanks

Not directly -- the UIPickerView can only have one data source at a time. However, you can switch data source when the user changes the segment. Note that you need to change the delegate of the picker view too, since it is the delegate that supplies the actual content of the picker.
Here is an example where you have two objects that implement UIPickerViewDataSource and UIPickerViewDelegate. The method is invoked when the user clicks on either of the segments in the control:
- (void)segmentedControlValueChanged {
switch (segmentedControl.selectedSegmentIndex) {
case 0:
pickerView.delegate = personDelegate;
pickerView.dataSource = personDelegate;
break;
case 1:
pickerView.delegate = placeDelegate;
pickerView.dataSource = placeDelegate;
break;
default:
break;
}
[pickerView reloadComponent:0];
}
But honestly, I think a better solution is to just have your pickerView:titleForRow:forComponent look at the segmented control.
Assuming you have two NSArrays called persons and places:
- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *result;
switch (segmentedControl.selectedSegmentIndex) {
case 0:
result = [self.persons objectAtIndex:row];
break;
case 1:
result = [self.places objectAtIndex:row];
break;
default:
result = #"Error!";
break;
}
return result;
}
- (void)segmentedControlValueChanged {
[pickerView reloadComponent:0];
}

You can check state of segmented control in your UIPickerView delegates (UIPickerViewDelegate and UIPickerViewDataSource) and return necessary values, depending on this state.
And, of course, you can create two objects (conforming to necessary protocols) and just reset delegates on segment state change. But I think this way is generally worse.

Related

Cant get values by choosing specific row in UIPickerView

i have a picker view with array of countries, and my point is, when user tap a specific row i will write some code depends of elements user choose, but, somehow its not working, please look at this:
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
if ([countries objectAtIndex:0]){
NSLog(#"You selected USA");
}
}
But problem is, in NSLog is always "You selected USA", regardless of which row i have pick. But, when i put that line of code here:
NSLog(#"You selected this: %#", [countries objectAtIndex:row]);
It show me in console which of country i have choose. But i need to do a things when user tap specific row, and i cant understand how to do this, please help me.
Quick answer: you should use
if ([[countries objectAtIndex:row] isEqualToString:#"USA"]) ...
Nice answer:
Define an enum and use switch-case structure:
// put this in the header before #interface - #end block
enum {
kCountryUSA = 0, // pay attention to use the same
kCountryCanada = 1, // order as in countries array
kCountryFrance = 2,
// ...
};
// in the #implementation:
-(void)pickerView:(UIPickerView *)pickerView
didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
switch (row) {
case kCountryUSA:
NSLog(#"You selected USA");
break;
case kCountryCanada:
NSLog(#"You selected Canada");
break;
case kCountryFrance:
NSLog(#"You selected France");
break;
//...
default:
NSLog(#"Unknown selection");
break;
}
}

How to change the picker rows based on another picker's selection?

I have two pickers - country and region. I need to populate the region picker based on the row selected in the country picker. I have arrays to populate both the pickers. I need some help to change the rows of region picker based on the country picker's selection. Any help would be greatly appreciated. Thanks a lot in advance.
Ok You have two pickers lets say countryPicker and regionPicker.
in the delegate method for UIPickerView add one condition
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
NSString *pickerTitle = #"";
if (pickerView == countryPicker)
{
pickerTitle = [countryFeeds objectAtindex:row];
//assigns the country title if pickerView is countryPicker
}
else if (pickerView == regionPicker)
{
pickerTitle = [regionFeeds objectAtindex:row];
//assigns the region title if pickerView is regionPicker
}
return pickerTitle;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (pickerView == countryPicker)
{
//selects the region corresponding to the selected country.
//totalRegions is a NSDictionary having country names as keys and array of their regions as values
regionFeeds = [totalRegions objectForKey:[countryFeeds objectAtindex:row]];
//Now reloading the regionPicker with new values.
[regionPicker reloadAllComponents];
}
else if (pickerView == regionPicker)
{
// your code to select a region
}
}
I hope this solves your problem :)
BR, Hari
Are they separate picker views, or one picker view with two columns?
Either way, when you change the value in one picker, just call reloadAllComponents on the other picker (or reloadComponent: if you are using a split picker) and then when it reloads the data from it's data source you can use the value from the first picker to supply the correct region list.
My suggestion is please maintain the country and region in one picker with two components(country,region).If u do like this then we can change the one component values based on another component value.
NSUInteger selectedRow= [CountryPicker selectedRowInComponent:0];
NSString *userchoice =[self pickerView:CountryPicker titleForRow:selectedRow forComponent:0];
This will give you the title for the selected row by the user in country picker
then using the arrays you have to populate names of regions
You can use
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated
on the RegionPicker

In iphone can i add one picker view on two text boxes /uilabel with diffrent values?

In my project i am filling the picker view array with the value which i am getting from the service.And in the same view i have another label on click of button in the label i want to get the same uipickerview with different value is that possible.....so with one picker view my work will be done no need to call to different picker views...anyone has solution for this isssue
i dont think so .. it will only be possible if you load the data again which means the uipicker(all same instance) with loaded with same data
of course this is possible. Just switch to another model that holds the data that is used in the picker.
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
if (myCurrentEditingValue == MyCountryValue) {
return ...
}
else if (myCurrentEditingValue == MyCityValue) {
return ...
}
return nil;
}
- (IBAction)startEditingCountryField {
myCurrentEditingValue = MyCountryValue;
[picker reloadAllComponents];
}
You should get the idea.

How does UIPickerView handle 2+ dials spinning?

If I have a UIPickerView with three components (dials). How does the picker handle two dials spinning simultaneously? For example, the user might flick the first dial, which spins freely and immediately slowly click to a selection on the second dial.
I'm doing the following in the picker. If one dial is spinning, I don't capture its value. I only capture values when the dials spin one at a time.
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
if(component == 0){
dateEndCenturyText = (NSString *)[dateCentury objectAtIndex:row];
}
else if(component == 1){
dateEndDecadeText = (NSString *)[dateYear objectAtIndex:row];
}
else if(component == 2){
dateEndYearText = (NSString *)[dateYear objectAtIndex:row];
}
Is there a better way to ensure capture of values even if two dials are spinning?
The most robust solution to this may be to update all three values each time your event fires. You can retrieve the selected row for any component in the UIPickerView using the following method:
UIPickerView selectedRowInComponent:
Returns the index of the selected row in a given component
- (NSInteger)selectedRowInComponent:(NSInteger)component
Hope this helps!

Multiple PickerViews in one View?

I want to create 2 separate pickers in the same view using the same viewController.
But how do I set separate delegates and datasource for them?
Can't seem to get it working. They show up with the same data. If you have any sample code on this it will be much appreciated.
Thanks.
Note that each method of both the datasource and the delegate protocols contain a UIPickerView * parameter, for instance:
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
You need to use it to distinguish between your two instances, as follows:
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
if([pickerView isEqual: pickerOne]){
// return the appropriate number of components, for instance
return 3;
}
if([pickerView isEqual: pickerTwo]){
// return the appropriate number of components, for instance
return 4;
}
}
The most straight forward way to do this is to use the tag property of the pickerView. I usually define these in the header for readability. You can set the tag in Interface Builder or in code.
#define kPickerOne 0
#define kPickerTwo 1
Then in your implementation file...
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
if(pickerView.tag == kPickerOne)
{
// do something with picker one
}
else if(pickerView.tag == kPickerTwo)
{
// the other picker
}
}