Скрыть ячейки в UITableView со статическими ячейками - и без сбоя автоаварии

У меня есть форма представления таблицы, созданная с использованием статических ячеек в IB/Storyboard. Тем не менее, мне нужно скрыть некоторые из ячеек во время выполнения в зависимости от определенных условий.

Я нашел несколько "ответов"; к этому вопросу о SO, например

UITableView установлен на статические ячейки. Можно ли программно скрыть некоторые из ячеек?

.. и они сосредоточены на установке высоты ячейки/строки на 0. Это замечательно, но теперь я получаю исключения из AutoLayout, потому что ограничения не могут быть выполнены. Как мне обойти эту последнюю проблему? Могу ли я временно отключить автоматическую компоновку для подзаголовка? Есть ли лучший способ сделать это в iOS7?

Ответы

Ответ 1

Я нашел, что лучший способ сделать это - просто обработать numberOfRowsInSection, cellForRowAtIndexPath и heightForRowAtIndexPath, чтобы выборочно удалить определенные строки. Вот пример "жесткого кодирования" для моего сценария, вы можете сделать что-то немного умнее, чтобы разумно удалить определенные ячейки, а не жесткий код, как это, но это было проще всего для моего простого сценария.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
    if (indexPath.section == 0 && hideStuff) {
        cell = self.cellIWantToShow;
    }
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat height = [super tableView:tableView heightForRowAtIndexPath:indexPath];
    if (indexPath.section == 0 && hideStuff) {
        height = [super tableView:tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];
    }
    return height;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSInteger count = [super tableView:tableView numberOfRowsInSection:section];

    if (section == 0 && hideStuff) {
        count -= hiddenCells.count;
    }

    return count;
}

Ответ 2

Скрыть ячейки на раскадровке и установить высоту в 0:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    let cell: UITableViewCell = super.tableView(tableView, cellForRowAtIndexPath:indexPath)
    return cell.hidden ? 0 : super.tableView(tableView, heightForRowAtIndexPath:indexPath)
    }
}

Ответ 3

Самый простой способ - изменить высоту разделов и строк. Меня устраивает.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 3) {
        return 0;
    } else {
        return [super tableView:tableView heightForHeaderInSection:section];
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
    if (indexPath.section == 3) {
        cell.hidden = YES;
        return 0;
    } else {
        cell.hidden = NO;
        return [super tableView:tableView heightForRowAtIndexPath:indexPath];
    }
}

Ответ 4

Кошерный способ сделать это - использовать динамические ячейки, установив высоту строки в 0, это взломать. Статические ячейки очень удобны, но ограничены по функциональности.

Ответ 5

Если вы гарантируете, что ограничение не будет касаться нижнего края ячейки, автозапуск не должен быть barf (проверен на iOS 6.0, 6.1, 7.0). Вы все равно "привяжетесь" к верхнему краю и должны будете выровнять высоты. (Конечно, вы можете сделать обратное и привязать к нижней части.)

Если ваш макет зависит как от верхнего, так и от нижнего края, может быть возможно программно удалить ограничения (они все-таки просто объекты).

Ответ 6

Мне удалось избежать исключений из Auto Layout, сначала удалив ограничения на ячейку contentView программно в viewDidLoad, а затем установив высоту ячейки в 0 в heightForRowAtIndexPath.

Ответ 7

Я нашел способ, который позволяет даже рисовать строки и работать с iOS 8.3. Все, что вам нужно, это реализовать метод tableView: numberOfRowsInSection:, а затем добавить/удалить строку с помощью методов UITableView insertRowsAtIndexPaths: withRowAnimation: и deleteRowsAtIndexPaths: withRowAnimation:.

Вот пример скрытия точной строки на основе состояния UISwitch:

- (IBAction)alowNotif:(id)sender {
    UISwitch *sw = (UISwitch*)sender;
    NSIndexPath *index = [NSIndexPath indexPathForRow:5 inSection:0];
    if ([sw isOn]) {
        [self.tableView insertRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
    else {
        [self.tableView deleteRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (![notifications isOn]) {
        return 5;
    }
    return 6;
}

Как было упомянуто выше @algal, numberOfRowInSection: по-прежнему является методом UITableViewDataSource, поэтому вы не просто знаете, как долго он будет работать.

Ответ 8

Лучший способ для меня - изменить метод numberOfRowsInSection. Я удалил источник данных, который я не хотел отображать. Лучшее решение для меня, потому что все в одной функции.

(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(section==0) {
    NSUInteger productCount = _products.count;
    for(loop trough your data) {
      if(your condition is true)
         productCount--;
      }
    }
    return productCount;
} else
    return self.groups.count;
}

Ответ 9

Реализовано это также для представления таблицы в StoryBoard. Мои ячейки встроены в разделы с заголовком, представленным этим синим кубом в xcode6 IB. Действительно, если вы реализуете heightForHeaderInSection, heightForFooterInSection и titleForHeaderInSection, titleForFooterInSection, вы можете получить доступ к заголовкам, когда отображается таблица, и вернуть 0.0 и nil соответственно и вернуть 0 для numberOfRowsInSection.

В принципе, все работает отлично, за исключением того, что для каждой ячейки скрыта ок. 10 пикселей вертикальное пространство остается для каждой ячейки (секции), которую вы скрываете. Любая идея, что это может быть?