UIPickerView падает при прокрутке 2 компонентов вместе
На самом деле, я задавал тот же вопрос раньше, но пока не нашел способа его исправить, так что я снова здесь.
Моя ситуация:
у меня есть UIPickerView
с двумя связанными компонентами, а количество и содержание строк во 2-м или правом компонентах изменяется в зависимости от текущей выбранной строки в 1-м или левом компоненте, что является довольно распространенной и полезной функцией UIPickerView
,
Теперь, если я использую 2 больших пальца для прокрутки обоих компонентов вместе, мое приложение очень быстро рушится, и вскоре появляется следующая информация:
*** Terminating app due to uncaught exception of class '_NSZombie_NSException'
libc++abi.dylib: terminate called throwing an exception
Ирония в том, что я не могу отладить это.
На самом деле, если я добавлю точку останова в pickerView:didSelectRow:inComponent
метод, я не могу даже быстро прокрутить оба компонента, так как он остановится в точке останова каждый раз, когда я просто нажимаю пальцем на экран.
Я могу только догадываться, причина в том, что, когда 1-й компонент прокручивается, предполагаемое количество строк во 2-м компоненте продолжает изменяться, но тем временем UIPickerView
запрашивает название и номер для 2-го компонента, а затем вылетает.
Но я не нашел ни одного метода, который можно было бы использовать для оценки прокрутки компонента. Поэтому я не могу найти правильное время, чтобы отклонить запрос pickerView
"s delegate
а также dataSource
для 2-го компонента.
Кто-нибудь сталкивался с подобной ситуацией?
Спасибо за вашу помощь! Я очень ценю это!
В моем коде ошибка о typePicker
, поэтому я удалил все остальные коды, не связанные с typePicker
,
Вот, type
а также detailTypes
два объекта в Базовых данных, и отношение ко многим называется details
достигает от type
в detailsTypes
,
Если тип "Наций", например, detailTypes
будет "США", "Франция", "Китай" и так далее.
Так что в typePicker
1-й или левый компоненты показывают все объекты типа, а 2-й или правый компоненты показывают соответствующие detailTypes
объекты в соответствии с текущим выбранным типом в 1-м компоненте.
И 1-й ряд обоих компонентов в typePicker
всегда имеет значение "Нет", чтобы позволить пользователям не выбирать конкретный тип, поэтому в коде много "+1".
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
if (pickerView == self.typePicker)
return 2;
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
NSUInteger majorTypeRow = [self.typePicker selectedRowInComponent:0] - 1;
if (pickerView == self.typePicker) {
if (component == 0)
return [self.types count] + 1;
else {
if (majorTypeRow == -1) // no major type entities
return 1;
NSString *majorTypeName = [[self.types objectAtIndex:majorTypeRow] name];
NSArray *detailType = [self.detailTypes objectForKey:majorTypeName];
if (detailType)
return [detailType count] + 1;
else {
NSManagedObject *majorType = [self.types objectAtIndex:majorTypeRow];
NSSet *minorTypes = [majorType valueForKey:@"details"];
NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:@"order" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sd, nil];
NSArray *array = [minorTypes sortedArrayUsingDescriptors:sortDescriptors];
[self.detailTypes setObject:array forKey:majorTypeName];
[sd release];
return [array count] + 1;
}
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSUInteger majorTypeRow = [self.typePicker selectedRowInComponent:0] - 1;
row--;
if (pickerView == self.typePicker) {
if (component == 0)
[pickerView reloadComponent:1]; // I believe this is where the bug starts, but I can't find the exact line of code that causes the crash
else {
if (row == -1)
self._detailType = nil;
else {
NSString *majorTypeName = [[self.types objectAtIndex:majorTypeRow] name];
NSArray *dt = [self.detailTypes objectForKey:majorTypeName];
if (dt)
self._detailType = [dt objectAtIndex:row];
}
}
}
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:path animated:YES scrollPosition:UITableViewScrollPositionNone];
}
2 ответа
Сбой из-за этой строки в ваших делегатах
NSUInteger majorTypeRow = [self.typePicker selectedRowInComponent:0] - 1;
Как уже указывалось другими, вам нужно сохранить два отдельных массива или объекта, которые могут предоставить источник данных для соответствующих компонентов.
У вас есть MajorType и detailType. Вы можете иметь массив majorTypes
и selectedMajorType
, Сохранение дополнительного selectedMajorType устраняет необходимость использования selectedRowInComponent:
и больше не вылетает приложение.
#pragma mark - UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
NSInteger rows = 0;
if (component) {
rows = [self.selectedMajorType.minorTypes count];
}else{
rows = [self.majorTypes count];
}
return rows+1;
}
Реализация UIPickerViewDelegate
- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
row--;
NSString *title = @"None";
if (component) {
NSArray *minorTypes = [self.selectedMajorType.minorTypes allObjects];
if (row >= 0 && row < [minorTypes count]) {
MinorType *minorType = minorTypes[row];
title = minorType.name;
}
}else{
if(row>=0 && row < [self.majorTypes count]){
MajorType *majorType = self.majorTypes[row];
title = majorType.name;
}
}
return title;
}
- (void)pickerView:(UIPickerView *)pickerView
didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
row--;
if (component==0) {
if (row >= 0 && row < [self.majorTypes count]) {
self.selectedMajorType = self.majorTypes[row];
}else {
self.selectedMajorType = nil;
}
[pickerView reloadComponent:1];
}
}
Ладно, думаю, я понимаю проблему:
Проблема с прокруткой двух компонентов заключается в том, что, поскольку ваш источник данных UIPickerView может меняться из-за зависимостей, которые вы создали с отношениями данных. Я думаю, что вам нужно создать два массива, которые представляют левый и правый соответственно и заполнить в зависимости от того, какой компонент вы меняете!
Решение может быть найдено, проверяя подобную проблему здесь! UIPickerView с двумя компонентами падает при прокрутке обоих
Кроме того, что касается проверки того, прокручивает ли ваш UIPickerView, вы можете просто установить таймер. Полезная ссылка здесь: Определение прокрутки UIPickerWheel! Проверяя, совпадают ли текущие строки, вы можете определить (в течение короткого интервала), переместил ли пользователь колесо!
Надеюсь это понятно и полезно!