View Full Version : Problem with my UIPicker xcode

Apr 18, 2011, 06:01 AM

I have recently started programming with xcode and my app launches fine in the simulator. The problem is I want to cover every movement combination of the Picker to produce different values in the label. Is it possible to do a sort of refresh on the picker after every movement so that each time it checks the 3 components after each movement?

// DoublePickerViewController.m
// DoublePicker
// Created by mac on 4/14/11.
// Copyright __MyCompanyName__ 2011. All rights reserved.

#import "DoublePickerViewController.h"

@implementation DoublePickerViewController
@synthesize doublePicker;
@synthesize osTypes;
@synthesize langTypes;
@synthesize threeTypes;

NSInteger langRow = [doublePicker selectedRowInComponent:
NSInteger osRow = [doublePicker selectedRowInComponent:
NSInteger threeRow = [doublePicker selectedRowInComponent:

NSString *lang = [langTypes objectAtIndex:langRow];
NSString *os = [osTypes objectAtIndex:osRow];
NSString *three = [threeTypes objectAtIndex:threeRow];

NSString *message = [[NSString alloc] initWithFormat:
@"Your %@ on %@ on %@ language will be right up.",lang, os, three];

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:
@"Thank you for your choice"
[alert show];
[alert release];
[message release];


- (void)viewDidLoad {
NSArray *langArray = [[NSArray alloc] initWithObjects:
@"203x133", @"254x102", nil];
self.langTypes = langArray;
[langArray release];

NSArray *osArray = [[NSArray alloc] initWithObjects:
@"Beam Y-Y", @"Beam X-X", nil];
self.osTypes = osArray;
[osArray release];

NSArray *threeArray = [[NSArray alloc] initWithObjects:
@"22", @"25", nil];
self.threeTypes = threeArray;
[threeArray release];


- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use.

- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.doublePicker = nil;
self.langTypes = nil;
self.osTypes = nil;
self.threeTypes = nil;
[super viewDidUnload];

- (void)dealloc {
[doublePicker release];
[langTypes release];
[osTypes release];
[threeTypes release];
[super dealloc];

#pragma mark -
#pragma mark Picker Data Source Methods

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
return 3;

- (NSInteger)pickerView:(UIPickerView *)pickerView
if (component == kLangComponent)
return [self.langTypes count];

return [self.osTypes count];
return [self.threeTypes count];

#pragma mark Picker Delegate Methods

- (NSString *)pickerView:(UIPickerView *)pickerView

if (component == kLangComponent)
return [self.langTypes objectAtIndex:row];

if (component == kOSComponent)
return [self.osTypes objectAtIndex:row];
if (component == kThreeComponent)
return [self.threeTypes objectAtIndex:row];


- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component

if (component == 0,1,2 && row == 0)

pickLabel.text = @"1001";


if (component == 0,2 && row == 0, component == 1 && row == 1)

pickLabel.text = @"1002";


if (component == 0,1 && row == 0, component == 2 && row == 1)
pickLabel.text = @"1006";


if (component == 1,2 && row == 0, component == 0 && row == 1)
pickLabel.text = @"1026";


if (component == 1,2 && row == 1, component == 0 && row == 1)
pickLabel.text = @"1031";






Apr 18, 2011, 10:24 AM
I'm confused by your question. Do you mean you want the label to change evey time the picker components are rotated without the use of a button?

Apr 18, 2011, 10:36 AM
Hey Shawnpk,

Yes thats correct. I am trying to create a 3 component pickerview that when you rotate an individual component it will look at the other 2 components and it will display text in a label.

Its easy for me to do it with 1 component pickerview but when there is 3, I am stuck on how to make them depend on each other to bring about a result that is displayed in the label.

Here below is an example of how I want my 3 pickerview to operate using below. (C = component.)

C1 C2 C3 changes to C1 C2 C3
1 a b 2 a b
2 c d c d

Label = 100 label = 200

Sorry I am new to all this. Thanks for your time.



C1 C2 C3
1 a b
2 c d

Label = 100

Picker then changes up to 2 in component 1 (1 goes off screen because it has been rolled up)

C1 C2 C3
2 a b
- c d

label = 200

Apr 18, 2011, 10:46 AM
I haven't tried this code myself, but see if it helps you:


Apr 19, 2011, 02:21 AM
Thanks for the link,

Its similar to what I am aiming to achieve but i need to have 3 components each producing a result to a textfield depending on a combination.


Apr 19, 2011, 09:25 AM
Are you saying you have a label with three characters and each character is determined by the corresponding value for that component in the picker?

Apr 19, 2011, 09:38 AM
Thanks for the link,

Its similar to what I am aiming to achieve but i need to have 3 components each producing a result to a textfield depending on a combination.


Right. Each component has an index number. The link shows only the first components index number. Use that and expand it to use three components.

Apr 19, 2011, 10:41 AM
I have managed to get this to work very easily with just 1 component in the picker because I have just used if statements to say that if the component 0 is on row 1 then put "hello" in the textview box, but when I have more than one component it gets more complex. So if I use if statements for Components 1,2,3 at row 0 every time the user picks row 0 on any component it puts the same value in the textview box. Its hard to explain..please look at my example below. Thanks for your time.

For example:

Component 1



Component 2



Component 3



If the combination of 1, B, and & are selected in the pickerview I would want to output a string of "Hello1" into a textview box

If the combination of 2, A, and & are selected in the pickerview I would want to output a string of "Hello2" into a textview box

I have managed to create a 3 component pickerview and by using if statements I can get it to output the string by saying if (component == 0,1,2 && row == 0)

but when the picker on compnent 1 and 2 go back to row 0 it over rides any other of the rows..

Any ideas of how I should approach this?

Thanks for your time.

Apr 19, 2011, 11:00 AM
I suspect the issue is with the construction of your if:
if (component == 0,1,2 && row == 0)
When component == 1 or 2, this evaluates to false (",1,2" is discarded). I don't think the comma operator is doing what you think it should be doing here. You should be getting a warning with this: "Expression result unused"; don't ignore it.

Apr 19, 2011, 11:21 AM
I'm not in front of my computer right now, so I can't try out your code, but I'm fairly sure that component == 0,1,2 won't work. You can break it up and use && between each component and the row and then set it to what you want.

Apr 19, 2011, 11:29 AM
As dejo mentions the if statements you show are gibberish. I guess they compile but they don't do anything like what you want them to do.

If you really have only a small number of combinations then you could use if logic to implement this. But your if statements (or switch statements would probably be better) need to be valid.

if (component1 == 0)
if (component2 == 0)
// etc...
else ...

But that is really a simplistic way of doing things and won't work if you end up with say 100 combinations or more.

The right way to do this is to LOOK UP the string based on the combinations. You could use a multidimensional array data model or a single array where the three component values are used to build an index into the array.

You could even use a database. SELECT result from RESULTS WHERE component1 = ? AND component2 = ? and component3 = ?. Let the database figure out how to find the result.

You might want to use a dictionary. Build a key from the three components to look up the result. NSString* key = [NSString stringWithFormat:@"%d_%d_%d", component1, component2, component2];

In all these implementations you build the data model earlier. You could build the database before running the app. The other implementations using arrays or a dictionary could be built in the view controller's viewDidLoad or init method or when the app starts up or could be built as a plist file that's just read in.

Anyway, choose one of these methods that makes sense and try that. Your code needs to be able to look up the answer in its data model in one line of code.

BTW, in the code you posted to don't even get the values for the components. I guess you don't understand that you need to use selectedRowInComponent: to get the current value of each component.

Also, if you use an array of arrays for your data model for the component labels you can simplify the logic in your titleForRow:forComponent: and numberOfRowsInComponent: methods.

Apr 20, 2011, 03:29 AM
Thanks for the help.

I dont suppose you know any good tutorials or similar projects I could look at for the dictionary look up to get my head around the code?

"You might want to use a dictionary. Build a key from the three components to look up the result. NSString* key = [NSString stringWithFormat:@"%d_%d_%d", component1, component2, component2];"



Apr 20, 2011, 10:59 AM
Does this 3-way picker have a real purpose, or is it just an example for learning?

Because if it's just an example, then it's obviously too complex for you to understand how to create it at this time. You should probably go back and review the fundamentals of stringWithFormat: and NSDictionary.

If the picker has a real purpose, then it's still too complex, so you should still review fundamentals, and then start with a simpler example.

Sstart with a plain 1-component picker, and make it work correctly just using picker values as label text. Then revise it to use an NSDictionary where the picker values are keys, and the label text is the value for the key. Once that's working perfectly, revise it to a 2-component picker, again with dictionaries and keys. Then you can try a 3-way picker.

Right now, it looks like you're in way over your head while learning to swim, and are simply flailing around on the verge of drowning.

Apr 20, 2011, 02:42 PM
chown is probably right that you're out of your depth here.

At any rate I'll leave you with this. In order to build and use a dictionary for the purpose described above it would make sense to write two methods

-(void)addResultStringForComponentsOne:(NSInteger)component1 two:(NSInteger)component2 three:(NSInteger)component3;

-(NSString)resultStringForComponentsOne:(NSInteger)component1 two:(NSInteger)component2 three:(NSInteger)component3;

You would build your dictionary using repeated calls to the first method, probably in viewDidLoad and you would get the result string using the second method and apply it to your label. The second method would look up the result string in the dictionary.

Good luck,

Apr 21, 2011, 02:25 AM
Hey you guys are right. I have bought a book for beginners, so I will spend my easter reading that.

Thanks for the help and pointers though.