UIPickerView updating from UISegmentedControl - ios

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.

Related

Add User data to UIPickerView

I have an app where the user scans a QR code into an NSString, which I then need to put into a UIPickerView.
What would I use to set the text of the UIPickerView row as the NSString from the QR code?
Firstly, you need to have an array of strings and implement the UIPickerViewDataSource and UIPickerViewDelegate in your .h file. After this, you will have to make use of the delegate methods of UIPickerView like as shown :
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
//return number.
}
This will return the number of sections that you want in your pickerView.
(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return array.count;
}
The above method will return the number of rows in particular component. If you have an array, then probably it will be equal to the number of elements in your array. And finally this last one.
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
NSString *str;
if(pickerView == yourPickerName)
{
str = [array objectAtIndex:row];
}
return str;
}
This method will return the text value for each row in your picker. And don't forget to connect your pickerView's datasource and delegate in your Storyboard.
Hope this helps.

UIPickerView and empty core data array

I have a viewcontroller showing items from a core data entity. I also have a tableview listing records from the same entity. The table is editable, and the user could remove all the records. When this happens, the view controller holding the pickerview bombs because it's looking for records in an empty array. How to prevent this? I'm assuming I need to do something different at objectAtIndex:row...
# 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"];
}
EDIT**
Ok, I found what was causing the problem...on the PickerView I was setting a default..
self.profiles = [[self.managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
selectedProfile = [[profiles objectAtIndex:0]valueForKey:#"profilename"];
[pickerView reloadAllComponents];
When I take that out, it works like a champ.

Getting row without selection from UIPickerView

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.

UIPickerView selectRow won't select last row during initialization

I have found similar questions here and here. I have tried the answers to these and other questions found on stackoverflow and Apple's developer forums, with no luck.
I created a fresh project to test this, and it works fine in that new project. I am iteratively removing differences between my new test project and the one exhibiting this issue. Any pointers would be most helpful.
I have a UIPickerView connected to my view controller. I want to initialize the UIPickerView to the last value selected by the user. However if this row is the last row in the picker, it shows the second-to-last row selected in the UI instead.
Meanwhile, logging shows the correct row index selected in the UIPickerView object instance.
Selecting any row besides the last row in the picker works fine.
I have tried calling the selectRow:inComponent:animated method from viewDidLoad, viewWillAppear, and viewDidAppear - none of these make any difference. I have also tried calling reloadAllComponents in various orders relative to row selection and data initialization - again, no difference.
Some code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSParameterAssert(self.pickerView);
// Set pickerView data
self.pickerOptions = #[#"zero", #"one", #"two", #"three", #"four"];
// Picker View config
self.pickerView.dataSource = self;
self.pickerView.delegate = self;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSInteger selectedIndex = ([self.pickerOptions count] -1);
NSLog(#"About to select row: %d", selectedIndex);
[self.pickerView selectRow:selectedIndex inComponent:0 animated:NO];
NSLog(#"Selected value is %d", [self.pickerView selectedRowInComponent:0]);
}
#pragma mark UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
NSInteger numRows = [self.pickerOptions count];
NSLog(#"numRows: %d", numRows);
return numRows;
}
#pragma mark UIPickerViewDelegate
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *rowTitle = [self.pickerOptions objectAtIndex:(NSUInteger)row];
return rowTitle;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *value = [self.pickerOptions objectAtIndex:(NSUInteger)row];
NSLog(#"User selected value: %#", value);
NSLog(#"index: %d", row);
}
Log output:
-[CCSelectorViewController viewDidAppear:] About to select row index: 4
-[CCSelectorViewController pickerView:numberOfRowsInComponent:] numRows: 5
-[CCSelectorViewController viewDidAppear:] Selected row index is 4
Here is the screenshot of the wrong row being selected:
http://imgur.com/FVvu9RA
This is using iOS6, XCode 4.6.1.
Any ideas?

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]];

Resources