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

UITableView установить в статические ячейки.

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

Ответ 1

Вы ищете это решение:

StaticDataTableViewController 2.0

https://github.com/xelvenone/StaticDataTableViewController

который может показывать/скрывать/перезагружать любые статические ячейки с анимацией или без нее!

[self cell:self.outletToMyStaticCell1 setHidden:hide]; 
[self cell:self.outletToMyStaticCell2 setHidden:hide]; 
[self reloadDataAnimated:YES];

Примечание: всегда использовать только (reloadDataAnimated: YES/NO) (не вызывайте [self.tableView reloadData] напрямую)

Это не использует хакерское решение с установкой высоты 0 и позволяет вам анимировать изменения и скрывать целые разделы

Ответ 2

Чтобы скрыть статические ячейки в UITable:

  • Добавить этот метод:

В классе делегирования контроллера UITableView:

Objective-C:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell* cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

    if(cell == self.cellYouWantToHide)
        return 0; //set the hidden cell height to 0

    return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}

Swift:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    var cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)

    if cell == self.cellYouWantToHide {
        return 0
    }

    return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}

Этот метод будет вызван для каждой ячейки в UITable. Как только он вызывает его для ячейки, которую вы хотите скрыть, мы устанавливаем ее высоту на 0. Мы идентифицируем целевую ячейку, создавая для нее выход:

  1. В конструкторе создайте розетку для ячейки, которую вы хотите скрыть. Выпуск для одной такой ячейки называется "cellYouWantToHide" выше.
  2. Отметьте "Подвижные элементы клипа" в IB для ячеек, которые вы хотите скрыть. Ячейки, которые вы скрываете, должны иметь ClipToBounds = YES. В противном случае текст будет накапливаться в UITableView.

Ответ 3

Лучший способ описан в следующем блоге http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/

Создайте свой статический вид таблицы как обычно в построителе интерфейса - в комплекте со всеми потенциально скрытыми ячейками. Но есть одна вещь, которую вы должен делать для каждой потенциальной ячейки, которую вы хотите скрыть - проверьте Свойство "Clip subviews" ячейки, иначе содержимое ячейка не исчезает, когда вы пытаетесь скрыть ее (уменьшая ее высота - более поздняя).

SO - у вас есть переключатель в ячейке, и переключатель должен скрыть и показать некоторые статические ячейки. Подключите его к IBAction, и там это:

[self.tableView beginUpdates];
[self.tableView endUpdates];

Это дает вам приятную анимацию для появления ячеек и исчезает. Теперь реализуем следующий метод делегирования представления таблицы:

- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 1 && indexPath.row == 1) { // This is the cell to hide - change as you need
    // Show or hide cell
        if (self.mySwitch.on) {
            return 44; // Show the cell - adjust the height as you need
        } else {
            return 0; // Hide the cell
        }
   }
   return 44;
}

И вот оно. Переверните переключатель, и ящик скрывается и снова появляется с приятная, плавная анимация.

Ответ 4

Мое решение идет в том же направлении, что и Гарет, хотя я делаю что-то по-другому.

Здесь:

1. Скрыть ячейки

Невозможно напрямую скрыть ячейки. UITableViewController - это источник данных, который предоставляет статические ячейки, и в настоящее время нет способа сказать "не предоставлять ячейку x". Поэтому мы должны предоставить собственный источник данных, который делегирует UITableViewController, чтобы получить статические ячейки.

Проще всего подклассом UITableViewController и переопределить все методы, которые должны вести себя по-разному при скрытии ячеек.

В простейшем случае (таблица с одним разделом все ячейки имеют одинаковую высоту), это будет выглядеть следующим образом:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section    
{
    return [super tableView:tableView numberOfRowsInSection:section] - numberOfCellsHidden;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Recalculate indexPath based on hidden cells
    indexPath = [self offsetIndexPath:indexPath];

    return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}

- (NSIndexPath*)offsetIndexPath:(NSIndexPath*)indexPath
{
    int offsetSection = indexPath.section; // Also offset section if you intend to hide whole sections
    int numberOfCellsHiddenAbove = ... // Calculate how many cells are hidden above the given indexPath.row
    int offsetRow = indexPath.row + numberOfCellsHiddenAbove;

    return [NSIndexPath indexPathForRow:offsetRow inSection:offsetSection];
}

Если ваша таблица имеет несколько разделов или ячейки имеют разную высоту, вам необходимо переопределить больше методов. Тот же принцип применяется здесь: вам нужно смещать indexPath, раздел и строку перед передачей на супер.

Также имейте в виду, что параметр indexPath для таких методов, как didSelectRowAtIndexPath:, будет отличаться для одной и той же ячейки, в зависимости от состояния (т.е. количества скрытых ячеек). Поэтому, вероятно, неплохо всегда смещать любой параметр indexPath и работать с этими значениями.

2. Анимировать изменение

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

Я узнал, что если вы сразу вызываете reloadData:, анимация значительно улучшится (осталось только незначительные глюки). После анимации таблица отображается правильно.

Итак, что я делаю:

- (void)changeState
{
     // Change state so cells are hidden/unhidden
     ...

    // Reload all sections
    NSIndexSet* reloadSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self numberOfSectionsInTableView:tableView])];

    [tableView reloadSections:reloadSet withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView reloadData];
}

Ответ 5

  • В дизайнере создайте розетку для ячейки (я), которую вы хотите скрыть. Например, вы хотите скрыть "cellOne", поэтому в viewDidLoad() выполните это

cellOneOutlet.hidden = true

теперь переопределить метод ниже, проверить, какой статус ячейки скрыт и вернуть высоту 0 для этих ячеек (ячеек). Это один из многих способов скрыть любую ячейку в static tableView в swift.

override func tableView(tableView: UITableView, heightForRowAtIndexPathindexPath: NSIndexPath) -> CGFloat 
{

let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)

        if tableViewCell.hidden == true
        {
            return 0
        }
        else{
             return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
        }

}

Ответ 6

Я придумал альтернативу, которая фактически скрывает разделы и не удаляет их. Я попробовал подход @henning77, но у меня возникали проблемы, когда я менял количество секций статического UITableView. Этот метод работал очень хорошо для меня, но я в первую очередь стараюсь скрыть разделы вместо строк. Я удаляю несколько строк на лету успешно, но это намного грязнее, поэтому я попытался сгруппировать вещи в разделы, которые мне нужно показать или скрыть. Вот пример того, как я скрываю разделы:

Сначала я объявляю свойство NSMutableArray

@property (nonatomic, strong) NSMutableArray *hiddenSections;

В viewDidLoad (или после запроса данных) вы можете добавлять разделы, которые вы хотите скрыть в массиве.

- (void)viewDidLoad
{
    hiddenSections = [NSMutableArray new];

    if(some piece of data is empty){
        // Add index of section that should be hidden
        [self.hiddenSections addObject:[NSNumber numberWithInt:1]];
    }

    ... add as many sections to the array as needed

    [self.tableView reloadData];
}

Затем реализуем следующие методы делегата TableView

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
        return nil;
    }

    return [super tableView:tableView titleForHeaderInSection:section];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
        return 0;
    }

    return [super tableView:tableView heightForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
        [cell setHidden:YES];
    }
}

Затем установите высоту заголовка и нижнего колонтитула в 1 для скрытых разделов, потому что вы не можете установить высоту в 0. Это вызывает дополнительное пространство в 2 пикселя, но мы можем компенсировать это, отрегулировав высоту следующего видимого заголовка.

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
{
    CGFloat height = [super tableView:tableView heightForHeaderInSection:section];

    if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
        height = 1; // Can't be zero
    }
    else if([self tableView:tableView titleForHeaderInSection:section] == nil){ // Only adjust if title is nil
        // Adjust height for previous hidden sections
        CGFloat adjust = 0;

        for(int i = (section - 1); i >= 0; i--){
            if([self.hiddenSections containsObject:[NSNumber numberWithInt:i]]){
                adjust = adjust + 2;
            }
            else {
                break;
            }
        }

        if(adjust > 0)
        {                
            if(height == -1){
                height = self.tableView.sectionHeaderHeight;
            }

            height = height - adjust;

            if(height < 1){
                height = 1;
            }
        }
    }

    return height;
}

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section 
{   
    if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
        return 1;
    }
    return [super tableView:tableView heightForFooterInSection:section];
}

Затем, если у вас есть определенные строки, которые можно скрыть, вы можете настроить numberOfRowsInSection и какие строки возвращаются в cellForRowAtIndexPath. В этом примере у меня есть раздел, который имеет три строки, где любые три могут быть пустыми и должны быть удалены.

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

    if(self.organization != nil){
        if(section == 5){ // Contact
            if([self.organization objectForKey:@"Phone"] == [NSNull null]){     
                rows--;
            }

            if([self.organization objectForKey:@"Email"] == [NSNull null]){     
                rows--;
            }

            if([self.organization objectForKey:@"City"] == [NSNull null]){     
                rows--;
            }
        }
    }

    return rows;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    return [super tableView:tableView cellForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}

Используйте этот метод offsetIndexPath для вычисления indexPath для строк, где вы условно удаляете строки. Не требуется, если вы только скрываете разделы

- (NSIndexPath *)offsetIndexPath:(NSIndexPath*)indexPath
{
    int row = indexPath.row;

    if(self.organization != nil){
        if(indexPath.section == 5){
            // Adjust row to return based on which rows before are hidden
            if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){     
                row++;
            }
            else if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Address"] != [NSNull null]){     
                row = row + 2;
            }
            else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] != [NSNull null] && [self.organization objectForKey:@"Email"] == [NSNull null]){     
                row++;
            }
            else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){     
                row++;
            }
        }
    }

    NSIndexPath *offsetPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section];

    return offsetPath;
}

Есть много способов переопределить, но то, что мне нравится в этом подходе, заключается в том, что оно повторно используется. Настройте массив hiddenSections, добавьте к нему, и он скроет правильные разделы. Скрытие строк немного сложнее, но возможно. Мы не можем просто установить высоту строк, которые мы хотим скрыть до 0, если мы используем сгруппированный UITableView, потому что границы не будут правильно нарисованы.

Ответ 7

Оказывается, вы можете скрывать и показывать ячейки в статическом UITableView - и с анимацией. И это не так сложно выполнить.

Демо-проект

Видеоролик демонстрационного проекта

Суть:

  • Use tableView:heightForRowAtIndexPath: для динамического определения высот ячейки на основе некоторого состояния.
  • Когда состояние изменяет живые ячейки, отображающие/скрывающиеся, вызывая tableView.beginUpdates();tableView.endUpdates()
  • Не вызывайте tableView.cellForRowAtIndexPath: внутри tableView:heightForRowAtIndexPath:. Используйте кешированные индексы для различения ячеек.
  • Не скрывайте ячейки. Вместо этого установите свойство "Подхваты клипа" в Xcode.
  • Используйте пользовательские ячейки (не Plain и т.д.), чтобы получить красивую скрывающую анимацию. Кроме того, корректно обрабатывайте автоматический макет для случая, когда высота ячейки == 0.

Дополнительная информация в моем блоге (русский язык)

Ответ 8

Да, это определенно возможно, хотя я борюсь с той же проблемой на данный момент. Мне удалось заставить клетки спрятаться, и все работает нормально, но я не могу сейчас оперировать аккуратно. Вот что я нашел:

Я прячу строки на основе состояния переключателя ON/OFF в первой строке первого раздела. Если переключатель включен, в нем находится одна строка ниже, в противном случае есть две разные строки.

У меня есть селектор, который вызывается при переключении коммутатора, и я устанавливаю переменную, чтобы указать, в каком состоянии я. Тогда я вызываю:

[[self tableView] reloadData];

Я переопределяю функцию tableView: willDisplayCell: forRowAtIndexPath:, и если ячейка должна быть скрыта, я делаю это:

[cell setHidden:YES];

Это скрывает ячейку и ее содержимое, но не удаляет занимаемое ею пространство.

Чтобы удалить пробел, переопределите функцию tableView: heightForRowAtIndexPath: и верните 0 для строк, которые должны быть скрыты.

Вам также необходимо переопределить tableView: numberOfRowsInSection: и вернуть количество строк в этом разделе. Вы должны сделать что-то странное здесь, чтобы, если ваша таблица сгруппирована, округлые углы встречаются на правильных ячейках. В моей статической таблице есть полный набор ячеек для секции, поэтому есть первая ячейка, содержащая эту опцию, затем 1 ячейку для опций состояния ON и еще 2 ячейки для опций состояния OFF, всего 4 ячейки. Когда опция включена, мне нужно вернуть 4, это включает скрытый параметр, чтобы последний отображаемый параметр имел закругленный прямоугольник. Когда опция выключена, последние два параметра не отображаются, поэтому я возвращаюсь 2. Это все неудобно. Извините, если это не очень понятно, его сложно описать. Чтобы проиллюстрировать настройку, это построение секции таблицы в IB:

  • Строка 0: Опция с переключателем ON/OFF
  • Строка 1: отображается, когда опция включена.
  • Строка 2: отображается, когда опция выключена
  • Строка 3: отображается, когда опция выключена

Поэтому, когда опция включена, таблица сообщает о двух строках:

  • Строка 0: Опция с переключателем ON/OFF
  • Строка 1: отображается, когда опция включена.

Когда опция выключена, таблица сообщает четыре строки, которые:

  • Строка 0: Опция с переключателем ON/OFF
  • Строка 1: отображается, когда опция включена.
  • Строка 2: отображается, когда опция выключена
  • Строка 3: отображается, когда опция выключена

Этот подход не кажется правильным по нескольким причинам, насколько это возможно, до сих пор, насколько я доволен своими экспериментами, поэтому, пожалуйста, дайте мне знать, если вы найдете лучший способ. Проблемы, которые я наблюдал до сих пор:

  • Неправильно говорить в таблице количество строк отличается от того, что предположительно содержится в базовых данных.

  • Я не могу оживить изменение. Я попытался использовать tableView: reloadSections: withRowAnimation: вместо reloadData, и результаты, похоже, не имеют смысла, я все еще пытаюсь заставить это работать. В настоящее время похоже, что tableView не обновляет правильные строки, поэтому остается скрытым, что должно отображаться, а пустота остается под первой строкой. Я думаю, что это может быть связано с первым пунктом о базовых данных.

Надеюсь, кто-то сможет предложить альтернативные методы или, возможно, продлить анимацию, но, возможно, это поможет вам начать. Мои извинения за отсутствие гиперссылок на функции, я вложил их, но они были отклонены фильтром спама, потому что я довольно новый пользователь.

Ответ 9

Согласно ответу Юстаса, но для Swift 4:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let cell = super.tableView(tableView, cellForRowAt: indexPath)

    if cell == self.cellYouWantToHide {
        return 0
    }

    return super.tableView(tableView, heightForRowAt: indexPath)
}

Ответ 10

Вышеупомянутые ответы, которые скрывают/показывают ячейки, меняют rowHeight или беспорядок с ограничениями автоматической компоновки, не работают для меня из-за проблем с автоматической компоновкой. Код стал невыносимым.

Для простой статической таблицы лучше всего для меня было:

  • Создать выход для каждой ячейки в статической таблице
  • Создайте массив только с выводами ячеек, чтобы показать
  • Переопределить cellForRowAtIndexPath для возврата ячейки из массива
  • Заменить numberOfRowsInSection, чтобы вернуть счетчик массива
  • Внедрить метод определения того, какие ячейки должны быть в этом массиве, и вызывать этот метод при необходимости, а затем перезагружать данные.

Вот пример моего контроллера табличного представления:

@IBOutlet weak var titleCell: UITableViewCell!
@IBOutlet weak var nagCell: UITableViewCell!
@IBOutlet weak var categoryCell: UITableViewCell!

var cellsToShow: [UITableViewCell] = []

override func viewDidLoad() {
    super.viewDidLoad()
    determinCellsToShow()
}

func determinCellsToShow() {
    if detail!.duration.type != nil {
        cellsToShow = [titleCell, nagCell, categoryCell]
    }
    else {
        cellsToShow = [titleCell,  categoryCell]
    }
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    return cellsToShow[indexPath.row]
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return cellsToShow.count
}

Ответ 11

Ладно, после некоторых попыток у меня есть необычный ответ. Я использую переменную isHidden или hidden, чтобы проверить, должна ли эта ячейка быть скрытой.

  1. создайте IBOutlet для вашего контроллера представления. @IBOutlet weak var myCell: UITableViewCell!

  2. Обновите myCell в вашей пользовательской функции, например, вы можете добавить ее в viewDidLoad:

override func viewDidLoad() { super.viewDidLoad() self.myCell.isHidden = true }

  1. в вашем методе делегата:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) → CGFloat { let cell = super.tableView(tableView, cellForRowAt: indexPath) guard !cell.isHidden else { return 0 } return super.tableView(tableView, heightForRowAt: indexPath) }

Это уменьшит вашу логику в методе делегата, и вам нужно только сосредоточиться на ваших бизнес-требованиях.

Ответ 12

Я нашел решение для сокрытия ячеек в статической таблице.

// Class for wrapping Objective-C block
typedef BOOL (^HidableCellVisibilityFunctor)();
@interface BlockExecutor : NSObject
@property (strong,nonatomic) HidableCellVisibilityFunctor block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block;
@end
@implementation BlockExecutor
@synthesize block = _block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block
{
    BlockExecutor * executor = [[BlockExecutor alloc] init];
    executor.block = block;
    return executor;
}
@end

Требуется только один дополнительный словарь:

@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end

И посмотрите на реализацию MyTableViewController. Нам нужны два метода для преобразования indexPath между видимыми и невидимыми индексами...

- (NSIndexPath*)recoverIndexPath:(NSIndexPath *)indexPath
{
    int rowDelta = 0;
    for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
    {
        BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
        if (ip.section == indexPath.section
            && ip.row <= indexPath.row + rowDelta
            && !executor.block())
        {
            rowDelta++;
        }
    }
    return [NSIndexPath indexPathForRow:indexPath.row+rowDelta inSection:indexPath.section];
}

- (NSIndexPath*)mapToNewIndexPath:(NSIndexPath *)indexPath
{
    int rowDelta = 0;
    for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
    {
        BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
        if (ip.section == indexPath.section
            && ip.row < indexPath.row - rowDelta
            && !executor.block())
        {
            rowDelta++;
        }
    }
    return [NSIndexPath indexPathForRow:indexPath.row-rowDelta inSection:indexPath.section];
}

Один IBAction для изменения значения UISwitch:

- (IBAction)birthdaySwitchChanged:(id)sender
{
    NSIndexPath * indexPath = [self mapToNewIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
    if (self.birthdaySwitch.on)
        [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    else
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}

Некоторые методы UITableViewDataSource и UITableViewDelegate:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    int numberOfRows = [super tableView:tableView numberOfRowsInSection:section];
    for (NSIndexPath * indexPath in [self.hidableCellsDict allKeys])
        if (indexPath.section == section)
        {
            BlockExecutor * executor = [self.hidableCellsDict objectForKey:indexPath];
            numberOfRows -= (executor.block()?0:1);
        }
    return numberOfRows;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    indexPath = [self recoverIndexPath:indexPath];
    return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    indexPath = [self recoverIndexPath:indexPath];
    return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // initializing dictionary
    self.hidableCellsDict = [NSMutableDictionary dictionary];
    [self.hidableCellsDict setObject:[BlockExecutor executorWithBlock:^(){return self.birthdaySwitch.on;}] forKey:[NSIndexPath indexPathForRow:1 inSection:1]];
}

- (void)viewDidUnload
{
    [self setBirthdaySwitch:nil];
    [super viewDidUnload];
}

@end

Ответ 13

Ответ в быстро:

Добавьте в свой TableViewController следующий метод:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}

если tableView пытается нарисовать ячейку, которую вы хотите скрыть, тогда она не отобразится, потому что ее высота будет установлена ​​на 0pt, благодаря вышеописанному методу все остальное останется неизменным.

Обратите внимание, что indexPathOfCellYouWantToHide можно изменить в любое время:)

Ответ 14

В > Swift 2.2, я собрал здесь несколько ответов.

Сделайте выход из раскадровки, чтобы ссылаться на ваш staticCell.

@IBOutlet weak var updateStaticCell: UITableViewCell!

override func viewDidLoad() {
    ...
    updateStaticCell.hidden = true
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if indexPath.row == 0 {
        return 0
    } else {
        return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
    }
}

Я хочу скрыть свою первую ячейку, чтобы установить высоту в 0, как описано выше.

Ответ 15

Простой способ совместимости с IOS 11 и IB/Storyboard

Для iOS 11 я обнаружил, что улучшенная версия ответа Мохамеда Салеха работала лучше всего, с некоторыми улучшениями, основанными на документации Apple. Он анимирует красиво, избегает любых уродливых хаков или жестко заданных значений, а использует высоты строк, уже установленные в Interface Builder.

Основная концепция - установить высоту строки в 0 для любых скрытых строк. Затем используйте tableView.performBatchUpdates, чтобы вызвать анимацию, которая работает последовательно.

Задайте высоты ячеек

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath == indexPathOfHiddenCell {
        if cellIsHidden {
            return 0
        }
    }
    // Calling super will use the height set in your storyboard, avoiding hardcoded values
    return super.tableView(tableView, heightForRowAt: indexPath)
}

Вы должны убедиться, что cellIsHidden и indexPathOfHiddenCell установлены соответствующим образом. Для моего кода они являются свойствами моего контроллера табличного представления.

Переключение ячейки

В любом методе, контролирующем видимость (вероятно, действие кнопки или didSelectRow), переключите состояние cellIsHidden внутри блока performBatchUpdates:

tableView.performBatchUpdates({
                // Use self to capture for block
                self.cellIsHidden = !self.cellIsHidden 
            }, completion: nil)

Apple рекомендует performBatchUpdates по beginUpdates/endUpdates, когда это возможно.

Ответ 16

Swift 4:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    var height = super.tableView(tableView, heightForRowAt: indexPath)
    if (indexPath.row == HIDDENROW) {
        height = 0.0
    }
    return height
}

Ответ 17

Для самого простого сценария, когда вы скрываете ячейки в самом низу таблицы, вы можете настроить tableView contentInset после скрытия ячейки:

- (void)adjustBottomInsetForHiddenSections:(NSInteger)numberOfHiddenSections
{
    CGFloat bottomInset = numberOfHiddenSections * 44.0; // or any other 'magic number
    self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, -bottomInset, self.tableView.contentInset.right);
}

Ответ 18

Это новый способ сделать это, используя https://github.com/k06a/ABStaticTableViewController

NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]

Ответ 19

Решение от k06a (https://github.com/k06a/ABStaticTableViewController) лучше, потому что оно скрывает целую секцию, включая верхние и нижние колонтитулы ячеек, где это решение (https://github.com/peterpaulis/StaticDataTableViewController) скрывает все, кроме нижнего колонтитула.

ИЗМЕНИТЬ

Я нашел решение, если вы хотите скрыть нижний колонтитул в StaticDataTableViewController. Это то, что вам нужно скопировать в файле StaticTableViewController.m:

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return nil;
    } else {
        return [super tableView:tableView titleForFooterInSection:section];
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {

    CGFloat height = [super tableView:tableView heightForFooterInSection:section];

    if (self.originalTable == nil) {
        return height;
    }

    if (!self.hideSectionsWithHiddenRows) {
        return height;
    }

    OriginalSection * os = self.originalTable.sections[section];
    if ([os numberOfVissibleRows] == 0) {
       //return 0;
        return CGFLOAT_MIN;
    } else {
        return height;
    }

    //return 0;
    return CGFLOAT_MIN;
}

Ответ 20

Конечно, вы можете. Во-первых, вернитесь к своему номеру таблицы TableView, который вы хотите показать, затем вызовите super, чтобы получить определенную ячейку из вашей раскадровки и вернуть ее для tableView:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.mode.numberOfCells()
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = super.tableView(tableView, cellForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))

    return cell
}

Если ваши ячейки имеют разный hieght, верните его тоже:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
}

Ответ 21

В дополнение к решению @Saleh Masum:

Если вы получаете ошибки автоматического макета, вы можете просто удалить ограничения из tableViewCell.contentView

Swift 3:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let tableViewCell = super.tableView(tableView, cellForRowAt: indexPath)

    if tableViewCell.isHidden == true
    {
        tableViewCell.contentView.removeConstraints(tableViewCell.contentView.constraints)
        return 0
    }
    else{
        return super.tableView(tableView, heightForRowAt: indexPath)
    }

}

Это решение зависит от потока вашего приложения. Если вы хотите показать/скрыть ячейку в том же экземпляре контроллера представления, это может быть не лучшим выбором, потому что он удаляет ограничения.

Ответ 22

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

Установка высоты строки в 0 может скрыть строку, но это не сработает, если вы хотите скрыть целый раздел, который будет содержать некоторые пробелы, даже если вы скрываете все строки.

Мой подход заключается в создании массива разделов статических ячеек. Затем содержимое табличного представления будет управляться массивом section.

Вот пример кода:

var tableSections = [[UITableViewCell]]()

private func configTableSections() {
    // seciton A
    tableSections.append([self.cell1InSectionA, self.cell2InSectionA])

    // section B
    if shouldShowSectionB {
        tableSections.append([self.cell1InSectionB, self.cell2InSectionB])
    }

    // section C
    if shouldShowCell1InSectionC {
        tableSections.append([self.cell1InSectionC, self.cell2InSectionC, self.cell3InSectionC])
    } else {
        tableSections.append([self.cell2InSectionC, self.cell3InSectionC])
    }
}

func numberOfSections(in tableView: UITableView) -> Int {
    return tableSections.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return tableSections[section].count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return tableSections[indexPath.section][indexPath.row]
}

Таким образом, вы можете собрать весь свой код конфигурации без необходимости написания неприятного кода для расчета количества строк и разделов. И, конечно же, больше нет 0 высот.

Этот код также очень прост в обслуживании. Например, если вы хотите добавить/удалить больше ячеек или разделов.

Аналогично, вы можете создать массив заголовков разделов и заголовок нижнего колонтитула раздела, чтобы динамически конфигурировать заголовки разделов.