2013-04-21 3 views
3

На самом деле, я задал один и тот же вопрос раньше, но я еще не нашел способ исправить его, поэтому здесь я снова нахожусь.UIPickerView падает при прокрутке 2 компонентов вместе

Моя ситуация:

У меня есть UIPickerView с 2 связанных компонентами, а также количество и содержание строк в 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-го компонента предполагаемое количество строк во втором компоненте продолжает меняться, но в то же время UIPickerView запрашивает название и номер для второго компонента, затем он сбои.

Но я не нашел метода, который можно использовать для определения того, прокручивается ли компонент. Поэтому я не могу найти правильное время, чтобы отклонить запрос pickerViewdelegate и dataSource для второго компонента.

Неужели кто-нибудь сталкивался с подобной ситуацией?

Благодарим за помощь! Я был бы признателен за это!


В моем коде, ошибка составляет около typePicker, поэтому я удалил все другие коды, не связанные с typePicker.

Здесь type и detailTypes две сущности в Core Data, и отношения ко многим называется 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]; 
} 
+0

Если вопрос не получает внимания вам нужно начать щедрот для него. Можете ли вы показать свою реализацию делегатов UIPicker? – Anupdas

+0

Конечно, я могу, но в этих методах много кода, так как логика довольно сложная, я боюсь, что куча странного кода напугает людей ., =. = Мне действительно нужно? –

+0

Убедитесь, что ваш источник данных всегда имеет действительные данные, и вы не упускаете каких-либо особых условий в своей логике. Отображение кода может избежать многих диких догадок. – Anupdas

ответ

6

Аварии из-за этой линии в ваших делегатов

NSUInteger majorTypeRow = [self.typePicker selectedRowInComponent:0] - 1; 

Как другие указывали на других, вы должны держать два отдельных массивов или объектов, которые могут обеспечить DataSource для соответствующих компонентов.

У вас есть 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]; 
    } 
} 

Demo Source Code

+0

Спасибо, кажется, хорошо, я собираюсь попробовать это сегодня. –

+0

Спасибо человеку, оказалось, что в этом коде было по меньшей мере 3 ошибки, которые вызвали крах, и один из них был тем, что вы указали. Начиная с вашей помощи, я думаю, что исправил их все! lol –

+0

@Eno Это удовольствие. Счастливое кодирование. – Anupdas

1

Хорошо, я думаю, я понимаю проблему:

Проблема с прокруткой двух компонентов вместе в том, что в качестве источника данных UIPickerView может измениться из-за dependecies вы создали с отношениями данных.Я думаю, вам нужно создать два массива, которые представляют собой левый и правый соответственно, и повторно заселяться на основе того, какой компонент вы меняете!

Решение может быть найдено, пройдя аналогичную проблему здесь! UIPickerView with two components crashes when scrolling both

Кроме того, что касается проверки того, прокручивается ли ваш UIPickerView, вы можете просто настроить таймер. Полезная ссылка: Determining if UIPickerWheel is scrolling! Проверяя, соответствуют ли текущие строки, вы можете сказать (в течение короткого промежутка времени), если пользователь переместил колесо!

Надеюсь, это ясно и полезно!

+0

Человек, ссылка на решение - это тот же вопрос, который я задал раньше. –