Отображение и скрытие UITableViewCell с UISwitch слишком быстрыми сбоями - PullRequest
6 голосов
/ 07 февраля 2012

У меня есть UITableView, который представляет некоторые настройки для пользователя.Некоторые ячейки скрыты, если переключатель UIS не находится в положении «Вкл.».У меня есть следующий код:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return switchPush.on ? 6 : 1;
}

// Hooked to the 'Value Changed' action of the switchPush
- (IBAction)togglePush:(id)sender {
    NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:0];
    for(int i = 1; i <= 5; i++) {
        [indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
    }

   [tableView beginUpdates];
    if(switchPush.on) {
        [tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
    } else {
        [tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
    }
   [tableView endUpdates];
}

Это работает, как и ожидалось, пока я дважды не переключу UISwitch в быстрой последовательности (двойным нажатием), и в этом случае приложение вылетает с

Invalid table view update. The application has requested an update to the table view that is inconsistent with the state provided by the data source.

Я знаю, что это вызвано неправильным возвращаемым значением numberOfRowsInSection, поскольку переключатель возвращается в исходное положение, пока анимация ячейки все еще воспроизводится.Я попытался отключить переключатель и перехватить код под другими обработчиками событий, но, похоже, ничто не может предотвратить сбой.Использование reloadData вместо анимации также решает проблему, но я бы предпочел хорошие анимации.

Кто-нибудь знает правильный способ реализации этого?

Ответы [ 4 ]

3 голосов
/ 10 мая 2012

Другое (более изящное) решение проблемы заключается в следующем:

Я изменил метод Алана МакГрегора - (IBAction)SwitchDidChange:(id)sender следующим образом:

- (IBAction)SwitchDidChange:(UISwitch *)source {
     if (_showRows != source.on) {
         NSArray *aryTemp = [[NSArray alloc] initWithObjects:
                    [NSIndexPath indexPathForRow:1 inSection:0],
                    [NSIndexPath indexPathForRow:2 inSection:0],
                    [NSIndexPath indexPathForRow:3 inSection:0],
                    [NSIndexPath indexPathForRow:4 inSection:0],nil];
         [_tblView beginUpdates];
         _showRows = source.on;
         if (_showRows) {
             [_tblView insertSections:aryTemp withRowAnimation:UITableViewRowAnimationFade];
         }
         else {
             [_tblView deleteSections:aryTemp withRowAnimation:UITableViewRowAnimationFade];
         }
         [_tblView endUpdates];
     }
}

Остальные части остались без изменений.

2 голосов
/ 20 апреля 2012

У меня была эта проблема на моем, и способ избежать сбоя заключается в том, чтобы не использовать явно Uiswitch, а вместо этого передать информацию в логическое значение, вот как я это сделал.

Добавьте логическое значение в началовашего файла реализации

bool _showRows = NO;

Обновите код Uiswitch

- (IBAction)SwitchDidChange:(id)sender {

NSArray *aryTemp = [[NSArray alloc] initWithObjects:[NSIndexPath indexPathForRow:1 inSection:0],
                    [NSIndexPath indexPathForRow:2 inSection:0],
                    [NSIndexPath indexPathForRow:3 inSection:0],
                    [NSIndexPath indexPathForRow:4 inSection:0],nil];

if (_showRows) {
    _showRows = NO;
    _switch.on = NO;
    [_tblView  deleteRowsAtIndexPaths:aryTemp withRowAnimation:UITableViewRowAnimationTop];
}
else {
    _showRows = YES;
    _switch.on = YES;
    [_tblView insertRowsAtIndexPaths:aryTemp withRowAnimation:UITableViewRowAnimationBottom];
}
}

И, наконец, обновите свой номерOfRowsInSection

- (NSInteger)tableView:(UITableView *)tableView 
 numberOfRowsInSection:(NSInteger)section
{
if (section == 0) {

    if (_showRows) {
        return 5;
    }
    else {
        return 1;

    }      
}
return 0;  
}
2 голосов
/ 07 февраля 2012

Просто установите свойство enabled вашего коммутатора на NO, пока не будут выполнены обновления.

0 голосов
/ 25 ноября 2013

События UIControlEventValueChanged происходят, даже если значение элемента управления фактически не изменяется. поэтому togglePush вызывается, даже если значение переключателя не изменяется. когда вы быстро переключаете переключатель, вы не всегда можете включить / выключить> включить> выключить и т. д. возможно выключить> включить> включить> выключить.

Итак, вы получаете два дополнения подряд, вызывая две вставки один за другим. что явно плохо.

, чтобы исправить это, вам нужно запомнить, какое было предыдущее состояние кнопки (возможно, в ivar) и выполнять вставку (или удаление), только если новое значение (source.on) отличается от предыдущего значения .

...