Скрыть ячейки в 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 пикселей вертикальное пространство остается для каждой ячейки (секции), которую вы скрываете. Любая идея, что это может быть?