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.
Related
I have put a UIPickerView for the user to select how they are feeling; annoyed, happy, sad etc. However I cannot convert what they have selected to a string or text. Is it possible to do this? If not how can I save the row/option they have selected in the picker?
If i understood your question correctly, here's what is needed. Check out the project at this gitHub commit or download zip.
Using typedef enum: create a enumeration that holds all values of emotions; happy, okay, neutral, sad, unhappy, etc. All with unique values assigned to each one like so:
Header File
//Number Values for each value of emotion. Add new emotions to the bottom of list, sort will not
//be effected in this declartion
typedef enum : NSUInteger {
CTEmotionNone = 0,
CTEmotionHappy = 1,
CTEmotionOkay = 2,
CTEmotionNeutral = 3,
CTEmotionSad = 4,
CTEmotionUnhappy = 5,
CTEmotionVeryHappy = 6
} CDEmotions;
Translating Number Values to text: There's different ways to doing this part but i liked this. Create an inline method, or function, that will return a string for the corresponding value of emotion:
Header File
//Here is where the title for each number value will be transalated
static inline NSString * NSEmotionTitleForEmotion( CDEmotions emotion) {
switch (emotion) {
case CTEmotionNone:
return #"Empty"; break;
case CTEmotionVeryHappy:
return #"Very Happy"; break;
case CTEmotionHappy:
return #"Happy"; break;
case CTEmotionOkay:
return #"Okay"; break;
case CTEmotionNeutral:
return #"Neutral"; break;
case CTEmotionSad:
return #"Sad"; break;
case CTEmotionUnhappy:
return #"Unhappy"; break;
}
}
Now the Order: creating another inline method, but this time returning an array with the order you want to display the emotions:
Header File
//Sorted int values in this array. Sort will be shown here. Do not put text in here, because then
//to know what "Very Happy" is you'll ahve to compare it to a string vs just saying 1 == 1, that
//means CTEmotionHappy
static inline NSArray * NSEmotionsList() {
return [NSArray arrayWithObjects:
#(CTEmotionNone),
#(CTEmotionVeryHappy),
#(CTEmotionHappy),
#(CTEmotionOkay),
#(CTEmotionNeutral),
#(CTEmotionSad),
#(CTEmotionUnhappy), nil];
}
Now using these functions will be fun :) I'll do it in your case using - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component from the UIPickerViewDataSource:
ViewController.h
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [NSEmotionsList() count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return NSEmotionTitleForEmotion( [[NSEmotionsList() objectAtIndex: row] intValue]);
}
And lastly implement the delegate method - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
[labelEmotion setText: NSEmotionTitleForEmotion( [[NSEmotionsList() objectAtIndex: row] intValue])];
}
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.
I have a pickerview that loads from a core data fetch on the view controller did load method. Everything works great, however I'm finding that I'm passing null values quite often, and that I'm having to spin the picker back and forth and click several times to get the value to hold.
I also have a problem if the user doesn't manually pick something, I need it to pass the value that the picker is on. I have a datepicker on the same viewcontroller and it passes whatever date it is sitting on without any problems. I'm probably overlooking something..any help would be appreciated
# pragma mark PickerView Section
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1; // returns the number of columns to display.
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [profiles count]; // returns the number of rows
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
// Display the profiles we've fetched on the picker
Profiles *prof = [profiles objectAtIndex:row];
return prof.profilename;
}
//If the user chooses from the pickerview
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
selectedProfile = [[profiles objectAtIndex:row]valueForKey:#"profilename"];
}
# pragma mark Segue Section
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"resultsSegue"]) {
ResultsVC *result = segue.destinationViewController;
result.profileName = [NSString stringWithFormat:#"%#",selectedProfile];
NSDate *selectedDate = [datePicker date];
result.trialDate = selectedDate;
}
}
You need to initialize selectedProfile to the 1st value in the picker. Do this in viewDidLoad. This way if the user never explicitly picks a value, the selectedProfile will be set to the 1st value by default.
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]];
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.