Using a UISegmentedControl to switch between multiple arrays using a uipickerview - iphone

I am working on a core data using app and one of the views is EditingViewController, which acts as the controller for a number of ui elements which describe the attributes of objects. Inside the EditingViewController, all of my ui elements are being called and hidden with the .hidden = YES/NO; operation. One of my ui elements is a uipickerview. Currently, there is one array for each of two different views. Meaning that if they clicked on the first name field, array1 would load in picker1, and they would pick from it, and then if they clicked on last name, array2 would load in picker2, and life is good. Here is my code I am using to make this work up until now:
- (NSString *)pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent:(NSInteger)component;
{
if (picker1 == self.picker) {
return [array1 objectAtIndex:row];
} else {
return [array2 objectAtIndex:row];
}
}
But! array1 is so big that I would like to add a UISegmentedControl to picker1 so that it can sort array1's info a little better. I know that UISegmentedControl is just a pretty set of buttons, requiring IBActions to be linked and stuff, but how could I implement it so that in one of my views, the first one, just picker1 and array1 are managed by the UISegmentedControl? Is it possible to make it so that it is just a smooth sorting process? I figure I will break down array1 into other arrays based on the conditions I set in my UISegmentedControl, how do I link those so they look and work good? Any help on this topic as always is greatly appreciated! Thanks

Use the selectedSegmentIndex property.
For example:
enum {
SEGMENT1,
SEGMENT2,
SEGMENT3
};
- (NSString *)pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent:(NSInteger)component;
{
if (picker1 == self.picker) {
if (segmentedControl.selectedSegmentIndex == SEGMENT1) {
return [array1sub1 objectAtIndex:row];
} else if (segmentedControl.selectedSegmentIndex == SEGMENT2) {
return [array1sub2 objectAtIndex:row];
} else if (segmentedControl.selectedSegmentIndex == SEGMENT3) {
return [array1sub3 objectAtIndex:row];
}
} else {
return [array2 objectAtIndex:row];
}
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if (picker1 == self.picker) {
if (segmentedControl.selectedSegmentIndex == SEGMENT1) {
return [array1sub1 count];
} else if (segmentedControl.selectedSegmentIndex == SEGMENT2) {
return [array1sub2 count];
} else if (segmentedControl.selectedSegmentIndex == SEGMENT3) {
return [array1sub3 count];
}
} else {
return [array2 count];
}
}
Also, you will want to reload the picker when the segmented control changes, so you should link the segmented control's value-changed event with a method like this:
- (IBAction)handleValueChanged
{
[self.picker reloadAllComponents];
}

Related

UIpickerview containing 2 component, second should cotain 1component minus selected row ios

pickerview containing 2 component both having same data when I select first component then the selected component should not appear in second component
After you make a selection in the first component, remove the item from the datasource for the second component & reload the picker components. HTH.
Your question is not clear but on the basic of what i understood:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
string = [fistPickerArray objectAtIndex:row];
//do what ever logic you want
for(NSString str in secondArray)
{
if([string isEqualToString:str])
{
[secondPickerArray removeObject:str],
}
}
[picker reloadAllComponent];
}
write below code in didSelectRow method
if(component == 0) {
string = [yourarray objectAtIndex:row];
}
then in titleForRow method,
if(component == 1) { if([string isEqualToString:[yourarray objectAtIndex:row]]) { break; return nil; else{ return string; }
}
}

Two PickerViews with different values

This is my code for two pickerviews in one view controller. However its not working for me.
#pragma mark UIPickerViewDelegate methods
//PickerViewController.m
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {
switch ([thePickerView tag]) {
case 1: //purpose picker
return [m_arrPurpose count];
case 2: //second picker
return [m_arrSweep count];
default:
return 0;
break;
}
}
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
switch ([thePickerView tag]) {
case 1: //purpose picker
{
//cost.text = #"Test";
Purpose *prp = [m_arrPurpose objectAtIndex:row];
return [prp m_purposeName];
}
case 2: //second picker
{
OpenActivity *opn = [m_arrSweep objectAtIndex:row];
return [opn m_ahhaName];
}
default:
return #"";
break;
}
}
can any1 help me with this please..
thanks
It sounds like either your tags aren't set correctly or you havent connected the datasource and delegate methods for both pickers.
Add some NSLog statements in the numberOfRowsInComponent and titleForRow: methods.
Include the picker view object and the picker view's tag in the log, e.g.
NSLog(#"Rows in component for %#, tag %d",thePickerView,[thePickerView tag]);
And a different text in the titleForRow.
You should see two different objects - if not, your delegate and datasource are not connected. You should see tags 1 and 2 - if not, your tags are not set properly.
With this problem there was nothing wrong with my code It's just that I forgot to set tag's value to 1 and 2 in XIB.

UIpickerView populating multiple uitextFields in the same ScrollView

Hi I am developing an iphone app where I have populated a uipickerview and it works great with one uitextfield. But I have 6 uitextfield I need to populate and I am using the same uipickerview for each UItextfield.
I have working the Ipickerview loaded with array objects and it pops up when each field is touched. The problem is with the code below the UItextfields share the same data from the picker.
I can not figure out how to code so each field gets it own data from the UIPickerView row.
What Am I doing wrong? Any coding suggestions?
Thanks
#implementation BestViewController
-(NSInteger)numberOfComponentsInPickerView: (UIPickerView *)thePickerView
{ return 1; }
-(NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent: (NSInteger)component
{return [list count]; }
-(NSString *)pickerView:(UIPickerView *)thePickerview titleForRow:(NSInteger)row forComponent:(NSInteger)component
{return [list objectAtIndex:row]; }
-(void)pickerView:(UIPickerView *)thePickerview didSelectRow:(NSInteger)row inComponent: (NSInteger)component
{
uitextfield1.text = [list objectAtIndex:row];
utitextfield2.text = [list objectAtIndex:row];
}
- (void)viewDidLoad {
[super viewDidLoad];
uitextfield1.inputView = pickerView;
uitextfield2.inputView = pickerView;
list = [[NSMutableArray alloc] init];
[list addObject:#"a"];
[list addObject:#"b"];
[list addObject:#"c"];
[list addObject:#"d"];
}
You need to get hold of the current first responder and set its text property rather than explicitly setting a particular text field.
So,
-(void)pickerView:(UIPickerView *)thePickerview didSelectRow:(NSInteger)row inComponent: (NSInteger)component
{
// textFields is an NSArray holding each of the textfields that are using the picker as an input view
for (UITextField textField in textFields)
{
if ([textField isFirstResponder])
{
textField.text = [list objectAtIndex:row];
break;
}
}
}
There may be a more elegant way to find the current first responder, this is off the top of my head. textFields could possibly be an IBOutletCollection, but I haven't used those myself so I can't speak with much authority.
Here is how I would do it:
First, define several different pickers. Of course you use the same UIPickerView but you change one property that helps you distinguish them. There is different data for (almost) each text field. One convenient property that Apple designed exactly for this purpose is the tag, an arbitrary integer available to every UIView. You can assign the same tags to the UITextFields.
For example:
#define kFirstTextField 101
#define kSecondTextField 102
#define kThirdTextField 103
//... etc
In the method when the text field is touched:
[myPickerView setHidden:NO]; // or however you show the picker
[myPickerView setTag:textField.tag];
[myPickerView reloadAllComponents];
In the data methods of the picker:
-(NSString *)pickerView:(UIPickerView *)thePickerview
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
if (thePickerView.tag==kFirstTextField)
{ return [list1 count]; }
if (thePickerView.tag==kSecondTextField)
{ return [anotherOrTheSameList count]; }
// of course, you can also use a switch statement
return [defaultList count];
}
Do something similar in the titleForRow: method.
Finally, when something is picked, discriminate again by tag:
-(void) pickerView:(UIPickerView *)thePickerview
didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
UITextField *field = (UITextField *) [thePickerview.superview viewWithTag:thePickerview.tag];
// this assumes the UIPickerView is the subview of the same view as the UITextFields
if (thePickerview.tag==kFirstTextField)
{ field.text = [list1 objectAtIndex:row]; }
if (thePickerview.tag==kSecondTextField)
{ field.text = [anotherOrTheSameList objectAtIndex:row]; }
// etc.
// alternatively:
field.text = [self pickerView:thePickerview titleForRow:row forComponent:0];
}

UIPickerView crashing when switching segemented control

I have four NSDictionaries that I would like to use to populate a pickerview depending on a segemented control.
With the code I have, the first segmented control/pickerview works fine but when I switch to the second segment the picker view only loads part of the second dictionary, that is it loads the same number of rows as it counted in the first dictionary. When I change the segmented control to the third or fourth segment it simply crashes with a sigabrt error indicating that it cannot index item43 when only 27 exist. This I suspect stems from a UItextfield population based on the upickerview row and object. I think the problem is with the way I have the data source and delegate set up.
#pragma mark -
#pragma mark UIPickerViewDelegate
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if ([wine selectedSegmentIndex] == 0)
{
return [robskeys objectAtIndex:row];
}
if ([wine selectedSegmentIndex] == 1)
{
return [esabskeys objectAtIndex:row];
}
if ([wine selectedSegmentIndex] == 2)
{
return [lebskeys objectAtIndex:row];
}
else if ([wine selectedSegmentIndex] == 3)
{
return [sbskeys objectAtIndex:row];
}
return #"Unknown title";
}
#pragma mark -
#pragma mark UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if ([wine selectedSegmentIndex] == 0)
{
return robskeys.count;
}
if ([wine selectedSegmentIndex] == 1)
{
return esabskeys.count;
}
if ([wine selectedSegmentIndex] == 2)
{
return lebskeys.count;
}
else if ([wine selectedSegmentIndex] == 3)
{
return sbskeys.count;
}
return 1;
}
#pragma mark -
Any help would be much appreciated
Thank you
UPDATE
Using the following when the segmentedcontrol is changed works. Does anyone see any problems in alloc, init, release the same picker view in viewDidLoad and in this IBAction. As you may have guessed the UItextfield winespec calls the coPicker not a keypad.
-(IBAction)ValueChanged:(id)sender {
[winespec resignFirstResponder];
UIPickerView *coPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
coPicker.tag = kCountryPickerTag;
coPicker.delegate = self;
coPicker.dataSource = self;
[coPicker setShowsSelectionIndicator:YES];
winespec.inputView = countryPicker;
[winespec becomeFirstResponder];
[coPicker release];
}
Are you reloading the UIPickerView when you switch the data source? (The reloadAllComponents method should do the trick.)
Irrespective, the problem is that an "out of index" row is being selected, so you'll probably also need to use the UIPickerView's selectedRowInComponent method to select a "safe" row (the first for example) when you switch the data source.
UPDATE
In essence, when you (effectively) change the current data source via the segmented control you need to set the selectedRowInComponent to zero and call reloadAllComponents on your UIPickerView. That should sort it all out. As such you could put this within the action you use to respond to the segmented control changes.

UIPickerView with 2 NSMutableArrays?

I have a core data based app I am working on, that uses an EditingViewController to control a number of different UI elements that get input from the user which describe attributes of an object that is subsequently stored within my app. The EditingViewController.xib file has such elements as a datePicker, textField, numberSlider, and where my problem is coming from a UIPickerView, that are all controlled within one view using .hidden = YES/NO; expressions. My problem is that I need to populate a UIPickerView in two seperate screens, that need to have two different NSMutableArray sources. Inside my viewDidLoad method I setup my first NSMutableArray:
listOfItems = [[NSMutableArray alloc] init];
[listOfItems addObject:#"Greenland"];
[listOfItems addObject:#"Switzerland"];
[listOfItems addObject:#"Norway"];
[listOfItems addObject:#"New Zealand"];
[listOfItems addObject:#"Greece"];
[listOfItems addObject:#"Rome"];
[listOfItems addObject:#"Ireland"];
And after that, I populate my UIPickerView *picker with this code:
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)picker;
{
return 1;
}
- (void)pickerView:(UIPickerView *)picker didSelectRow:(NSInteger)row inComponent: (NSInteger)component
{
label.text= [listOfItems objectAtIndex:row];// The label is simply setup to show where the picker selector is at
}
- (NSInteger)pickerView:(UIPickerView *)picker numberOfRowsInComponent:(NSInteger)component;
{
return 8;//[listOfItems count];
}
- (NSString *)pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent: (NSInteger)component;
{
return [listOfItems objectAtIndex:row];
}
And that works fine for the first attribute and array. So then after that, when a different uitableviewcell is selected, the picker is hidden picker.hidden = YES; and I need to have another picker, picker2 show up with a different array of information. But when I try and duplicate the process, by setting up a whole new picker, calling it picker2, and trying to populate it with a different NSMutableArray that I created right next to the first one (again, all because in my EditingViewController it's all part of the same view, just calling different UI elements depending on the view) I can't get picker2 to populate with the new array. I don't know how to set it up so that my two different arrays can be populated. Do I need two picker views? Can it be done with just one? What is the proper syntax in the - (NSString *)pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent: (NSInteger)component; method to make the two arrays viewable seperately? I hope someone can help me out on this, thank you in advance!
You are asking to use the same object as the delegate for two pickers.
In each of the delegate methods, the picker is provided as the first argument for this purpose. You can check which picker is passed in and return the appropriate data for that picker.
For example, if you add a property for the first picker named "pickerOne" and you second mutable array is called "arrayTwo", the delegate methods would look like this:
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)picker;
{
return 1; // assuming both pickers only have 1 component
}
- (void)pickerView:(UIPickerView *)picker didSelectRow:(NSInteger)row inComponent: (NSInteger)component
{
// The label is simply setup to show where the picker selector is at
if (picker == self.pickerOne) {
label.text= [listOfItems objectAtIndex:row];
} else {
label.text= [arrayTwo objectAtIndex:row];
}
}
- (NSInteger)pickerView:(UIPickerView *)picker numberOfRowsInComponent:(NSInteger)component;
{
if (picker == self.pickerOne) {
return [listOfItems count];
} else {
return [arrayTwo count];
}
}
- (NSString *)pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent: (NSInteger)component;
{
if (picker == self.pickerOne) {
return [listOfItems objectAtIndex:row];
} else {
return [arrayTwo objectAtIndex:row];
}
}
Also, you can populate your array like this (if you just have a static list of strings, the array does not need to be mutable):
listOfItems = [[NSArray alloc] initWithObjects:#"Baptisms",#"Greenland",#"Switzerland",#"Norway",#"New Zealand",#"Greece",#"Rome",#"Ireland",nil];