Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed an issue when initial selections applied to picker with different number of rows for different components. #113

Merged
merged 2 commits into from
Feb 9, 2015

Conversation

venj
Copy link

@venj venj commented Dec 12, 2014

Scenario

For example, the titles for two pickerView components are like this:

self.titles = @[ @[ @"Component 0 Row 0", @"Component 0 Row 1"],
                 @[ @"Component 0 Row 1", @"Component 1 Row 1", @"Component 1 Row 2", @"Component 1 Row 3"]
                ];

If the initial selections for pickerview are @[@(0), @(0)], there is no problem. But when initial selections are @[@(1), @(2)], there will be an app crash due to NSAssert([pv numberOfRowsInComponent:i] > row, @"Number of sections not match"); in - configuredPickerView.

Reason

I'm not very sure of the actual reason, but likely the reason is: set selected index for picker will not automatically call this UIPickerView delegate - pickerView:didSelectRow:inComponent:. In our case, we have different number of rows in different components, and we have to update the second component when selection is changed in the first component, before we set the second selection. If not, we will crash the app if the selection is beyond the range of rows in first selection in our case.

Solution

A manual call to - pickerView:didSelectRow:inComponent: delegate will fix the problem.

@venj venj changed the title Fixed an issue when initial selections applied to dynamically generated picker titles. Fixed an issue when initial selections applied to picker with different number of rows for different components. Dec 12, 2014
skywinder added a commit that referenced this pull request Dec 12, 2014
@skywinder
Copy link
Owner

Hi. First of all: Thanks for your contribution again with great explanation of the problem and solution!.
Actually I can't reproduce this bug.
I add test for this case, and it seems, that it works.

Also, you can check very similar case in example:

  1. Open Example.workspace
  2. Run ActionSheetPicker project
  3. Click on "Select a musical scale" button. - it reproduce the same logic that you descirbe. and it seems that it works as expected.

@skywinder
Copy link
Owner

@venj any updates?

@venj
Copy link
Author

venj commented Dec 23, 2014

@skywinder
I may not express myself clearly. So I made an example to show the crash:
https://github.com/venj/PickerExample

In my example, the first button clicked is just like the "musical scale"example. In the example, no matter what item is selected in component 0, component 1 will always have the same items. In that example, initial selections will work as long as they not beyond picker items' bound.

In my example, the second button clicked will also work. But the difference is, when selection in component 0 changed, items in component 1 will change accordingly. Since initial selections are (0,0), picker work fine.

If the last button clicked, set up is the same to second button. But initial selections are (1, 2). The selections are not beyond the bounds, but the app still crashes.

As I made this example, I found my pull request will not completely fix the bug, only prevent the app from crashing. I am looking into the issue now.

@skywinder skywinder added bug and removed unknown labels Dec 23, 2014
@skywinder
Copy link
Owner

@venj Wow. Thank you for such detail and high-quality explanation!
I confirm this bug. And will review it soon.


By the way:
Thanks to your project I found another bug: even if you add your fix and click on "Unbalanced crash" - there is only one row in second column. But should be 3.

// pickerView:didSelectRow:inComponent: automatically, so we manually call it.
if ( [_delegate respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)] )
{
[_delegate pickerView:pv didSelectRow:row inComponent:i];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your call [_delegate pickerView:pv didSelectRow:row inComponent:i]; just reload component from delegate method.

@skywinder
Copy link
Owner

@venj this bug can be solved in more universal way:
Replace your code with:

[pv reloadAllComponents];

Actually it will do the same thing (reloadComponents and update number of rows from delegate, thus app will not crash in the future selectRow:inComponent:animated: call)

This is more explicit way for the same job.

@skywinder
Copy link
Owner

I create separate issue #121 for the bug, that I described above.

But as you said: this fix prevent the app from crashing.
So, if you agree with my version of fix:
Let's change your code with [pv reloadAllComponents]; and I will merge it.

And then try to fix other issues.
Thanks for you outstanding work!

@skywinder skywinder merged commit 493899c into skywinder:master Feb 9, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants