How to read uipicker multiple component when one component is changed - ios

i have a 3component ui picker with index,days and time of consultation.
i want to read 2nd and 3rd component value when first component is changed.
What should i do to read 2nd and 3rd component in UIPicker when component 1 is changed?
days=#[#"Sunday",#"Monday",#"Tuesday",#"Wednesday",#"Thursday",#"Friday",#"Saturday"];
self.indexes=#[#"1",#"2",#"3",#"4",#"5",#"6",#"7"];
timeOfConsultation=#[#"9:00 AM",#"11:00 AM"];
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if(component == 0){
_labelValueIndex.text = [self.indexes objectAtIndex:row];
// When component 1 is spinned read component 2 and component 3 value even if they are not spinned
[days objectAtIndex:row];// incorrect value as row variable is like global if i select indexes[1] . i also get days[1] and timeOfConsultation [1]
// How to read component 2 and component 3 value from component1 change event
}else if (component == 1){
labelValueBookingDay.text = [days objectAtIndex:row];
}
else{
labelValueTimeOfConsultation.text = [timeOfConsultation objectAtIndex:row];
}
}

Use this code-
NSString *YourselectedTitle = [self.yourArrayName objectAtIndex:[self.yourPickerName selectedRowInComponent:1]];
NSLog(#"%#", YourselectedTitle);
Hope this helps!

Related

(iOS) How to make first value in UIPickerView unselectable?

I'm using UIPickerView with (for example) 4 rows. The first value is "Pick a value" with gray text. The others are values the user should pick with black text.
The picking is optional, so users could just skip it. But if they don't, how to make first value unselectable back after user will start picking?
Thanks.
Regards.
Use the UIPickerView delegate method - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component to change the selected row if the first row is selected :
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if (row == 0) {
[pickerView selectRow:row+1 inComponent:component animated:YES];
}
}
Edit : you may be able to change the text color using this :
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component {
if (row == 0)
return [[NSAttributedString alloc] initWithString:#"Pick a value" attributes:#{NSForegroundColorAttributeName:[UIColor lightGrayColor]}];
else {
// Return titles
}
}
This is if you target iOS 6+, and it replaces the previously used -pickerView:titleForRow:forComponent: method.

Objective C (UIPickerView): Do Action Once An Item Was Selected

On the app that I am developing I have a list of schedule on a UIPickerView and what I want to do is to enable a button once the 6th item on the list was selected.
I have this code but I it's not working
- (void)pickerView:(UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent:(NSInteger)component {
// Handle the selection
[trainSchedule setText:[NSString stringWithFormat:#"%#",[schedArray objectAtIndex:[pickerView selectedRowInComponent:0]]]];
if ([schedArray objectAtIndex:[schedArray objectAtIndex:[pickerView selectedRowInComponent:6]]]) { sendTrainRequest.enabled = YES; } else { sendTrainRequest.enabled = NO; }
}
I have this warning also...
Incompatible pointer to integer conversion sending 'id' to parameter of type 'NSUInteger' (aka 'unsigned int
How will a able to do what I want to happen?
I think you're looking for a UIPickerViewDelegate method called pickerView:didSelectRow:inComponent: documented here
I think the problem is in your if statement. If I am parsing what you are trying to say correctly, you want sendTrainRequest.enabled to be set to YES if the sixth item in the picker is selected. Your if statement now is confusing, and the warning is because you are sending on object to the objectAtIndex method of schedArray, when you should be sending an integer. Try this:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent:(NSInteger)component {
// Handle the selection
[trainSchedule setText:[NSString stringWithFormat:#"%#",[schedArray objectAtIndex:[pickerView selectedRowInComponent:0]]]];
if ([pickerView selectedRowInComponent:0] == 5)
{ sendTrainRequest.enabled = YES; }
else
{ sendTrainRequest.enabled = NO; }
}
Note that the hard-coded 5 in this snippet will evaluate to the sixth item in the picker view, since it is zero-referenced.

Displaying text from multiple components in UIPickerView

I need to display the values most recently selected in a multiple component pickerview in my label
I have a pickerView with three components, populated by three NSMutableArrays (rowOneItems,rowTwoItems,rowThreeItems).
I also have an NSLog statement that is correctly showing what the user last selected from the changed component.
However, I cannot figure out how to show the most recently selected values in the label properly.
Currently, the label takes the value from the first picker and displays it, but will not properly update the second and third values. Rather it selects the value that's in the same spot as it. For example, if all three arrays had the values of bird, dog, and cat, when I pick 'dog' in the picker view, the label will show three 'dog' values.
What I want to do is display the values of what the user has selected in the pickerview into a label.
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
inComponent:(NSInteger)component {
//log which row is selected in each component
//this shows the values correctly in output
if(component ==1) {
return NSLog(#"Selected Difficulty: %#",[rowTwoItems objectAtIndex:row]);
}
else if(component ==2) {
return NSLog(#"Selected Duration: %#",[rowThreeItems objectAtIndex:row]);
}
else{
NSLog(#"Selected Type: %#",[rowOneItems objectAtIndex:row]);
}
//define chosen items
//stuck here. tried using a if else statement as above, but of course that would only return the first value in the label
NSString *chosenType = [rowOneItems objectAtIndex:row];
NSString *chosenDifficulty = [rowTwoItems objectAtIndex:row];
NSString *chosenDuration = [rowThreeItems objectAtIndex:row];
[workoutResults setText:[NSString stringWithFormat:#"%#, %#, %#", chosenType, chosenDifficulty, chosenDuration]];
}
Just started learning obj-c, so my apologies if this is a total newbie question. Thanks for any guidance you can give me.
That method you've got above is called for a single row's change, and not for all. (So the 'row' variable) isn't useful outside of the row that was just changed. You'll want to call selectedRowInComponent:
NSString *chosenType = [rowOneItems objectAtIndex:[pickerView selectedRowInComponent:0]];
NSString *chosenDifficulty = [rowTwoItems objectAtIndex:[pickerView selectedRowInComponent:1]];
NSString *chosenDuration = [rowThreeItems objectAtIndex:[pickerView selectedRowInComponent:2]];

UIPickerView updating from UISegmentedControl

I'm attempting to update a single UIPickerView with a different NSArray of data based on which Index is selected from a UISegmentedControl. Currently when I change the control the numberOfRowsInComponent does not update, and the titleForRow will only update when scrolling the picker.
The NSArrays are populated within viewDidLoad, and I'm using the reloadAllComponents method upon an IBAction of the SegmentedControl.
#synthesize subnetView, classControl;
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
//One column
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
//set number of rows
if (classControl.selectedSegmentIndex == 0){
NSLog(#"Class A Rows %d", [classAArray count]);
return classAArray.count;
}
else if (classControl.selectedSegmentIndex == 1){
return classBArray.count;
}
else if (classControl.selectedSegmentIndex == 2){
return classCArray.count;
}
return 0;
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
//set item per row
if (classControl.selectedSegmentIndex == 0){
NSLog(#"Class A Rows %d", [classAArray count]);
return [classAArray objectAtIndex:row];
}
else if (classControl.selectedSegmentIndex == 1){
return [classBArray objectAtIndex:row];
}
else if (classControl.selectedSegmentIndex == 2){
return [classCArray objectAtIndex:row];
}
return 0;
}
-(IBAction)classChange{
[subnetView reloadAllComponents];
}
Based on which selector is chosen to be "selected" within interface builder, the picker is loaded with the correct array and number of rows. Based on this code when selecting an array with less elements, the numberOfRowsInComponents is not being updated, and the app will crash when reaching the end of the smaller array.
So my two problems:
Updating of elements only occurs when scrolling.
The number of rows does not update when performing the reloadAllComponents method.
Thanks for listening!
I've seen this before. Usually it is caused by the pickerview outlet not being connected, effectively calling reloadAllComponents on nothing. But when you scroll the connected data source and delegate methods still work.
This can be easily checked by login the outlet's value using:
NSLog(#"%#",subnetView);
If it logs (NULL) as I expect it will simply connect your IB outlet and you're done.

How do you make an UIPickerView component wrap around?

I would like to show a set of consecutive numbers in a UIPickerView component but have it wrap around like the seconds component of the Clock->Timer application. The only behavior I can enable looks like the hours component of the Timer application, where you can scroll in only one direction.
It's just as easy to set the number of rows to a large number, and make it start at a high value, there's little chance that the user will ever scroll the wheel for a very long time -- And even then, the worse that will happen is that they'll hit the bottom.
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
// Near-infinite number of rows.
return NSIntegerMax;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
// Row n is same as row (n modulo numberItems).
return [NSString stringWithFormat:#"%d", row % numberItems];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.pickerView = [[[UIPickerView alloc] initWithFrame:CGRectZero] autorelease];
// ...set pickerView properties... Look at Apple's UICatalog sample code for a good example.
// Set current row to a large value (adjusted to current value if needed).
[pickerView selectRow:currentValue+100000 inComponent:0 animated:NO];
[self.view addSubview:pickerView];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSInteger actualRow = row % numberItems;
// ...
}
I found my answer here:
http://forums.macrumors.com/showthread.php?p=6120638&highlight=UIPickerView#post6120638
When it asks for the title of a row, give it:
Code:
return [rows objectAtIndex:(row % [rows count])];
When it says the user didSelectRow:inComponent:, use something like this:
Code:
//we want the selection to always be in the SECOND set (so that it looks like it has stuff before and after)
if (row < [rows count] || row >= (2 * [rows count]) ) {
row = row % [rows count];
row += [rows count];
[pickerView selectRow:row inComponent:component animated:NO];
}
It appears that the UIPickerView does not support wrapping around natively, but you can fool it by inserting more sets of data to be displayed and when the picker stops, centering the component to the middle of the data set.
Just create an array multiple times, so that you have your numbers multiple times. Lets say when want to have the numbers from 0 to 23 and put that in an array. that we will do 10 times like this...
NSString *stdStepper;
for (int j = 0; j<10; j++) {
for(int i=0; i<24; i++)
{
stdStepper = [NSString stringWithFormat:#"%d", i];
[_hoursArray addObject:stdStepper];
}
}
later we set the row 0 selected like this
[_hoursPickerView selectRow:120 inComponent:0 animated:NO];

Resources