Custom UIPickerView - restricts the user to spin one wheel at a time

I have a custom UIPickerView with three components that are dependent on each other (i.e. the second shows the values โ€‹โ€‹depending on what was selected in the first, and the third depends on the first and second). I get the values โ€‹โ€‹that are displayed in the UIPickerView from an NSDictionary .

Everything works well, except that when two components are turned on simultaneously, the application sometimes crashes (there is no time to reload data). This is what my pickerView:didSelectRow:inComponent looks like pickerView:didSelectRow:inComponent :

 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { NSLog(@"Selecting row %d component %d", row, component); // When A is changed, we need to reload B and C if (component == 0) { [pickerView reloadComponent:1]; [pickerView selectRow:0 inComponent:1 animated:YES]; // need to reload the C after reloading B [self pickerView:pickerView didSelectRow:0 inComponent:1]; } else if (component == 1) { [pickerView reloadComponent:2]; [pickerView selectRow:0 inComponent:2 animated:YES]; } [self updateSelection]; } 

Is there a way to prevent more than one collector component from rotating at the same time to prevent a crash?

Thanks!

0
source share
2 answers

Good Saint Jesus, you call didSelectRow:component: recursively!

I know that the method of processing the parameters does not allow it to go through more than two levels, but still do not do this. Someday.

It is not possible to prevent multiple components from rotating at the same time. It is the joy of multitouch and iOS, so that everything sets in motion and watches how all this is consistent with a consistent state. And since spinner components take time to solve a problem, the user can customize them for each user using only one finger. You must learn to write your code accordingly.

In this case, you want to delete all calls to didSelectRow:component: from itself - it should be called only by the system. You are on the right track using reloadComponent: , it's just that you are not reloading them enough:

 -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { NSLog(@"Selecting row %d component %d", row, component); [self updateSelection]; // When A is changed, we need to reload B and C if (component == 0) { [pickerView reloadComponent:1]; [pickerView reloadComponent:2]; } else if (component == 1) { [pickerView reloadComponent:2]; } } 

I don't know what your updateSelection - apparently, it sets the data model based on the pickerView value. This is good - but it should happen at the top of your method, so when you call your titleForRow or viewForRow , it has the appropriate data to select from. Also, from any of these three ( update , titleFor , viewFor ) values do not state values โ€‹โ€‹in the collector! Just read it.

I think this is a good starting point for you, but you will have to pick things up a little here and there when you approach your goal. I think you will find that the key to Pickers is that they only claimed didSelectRow:component: when one of the spinner components of a thing settles to a value, and they are really good at continuing to spin if you reload them. Make it a shot and see if you can make some progress, send the word back if you're stuck.

+2
source

Spinning two wheels at a time means you have multitouch enabled, right? Thus, it is possible to simply disable multitouch and restrict the user to touch and operate only one wheel in the UIPickerView.

Here is a link that may help.

0
source

Source: https://habr.com/ru/post/1499895/


All Articles