it-swarm.com.ru

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

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

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

124
Shmidt

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

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 и позволяет вам анимировать изменения и скрывать целые разделы

48
Peter Lapisu

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

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

В вашем классе делегата контроллера 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's 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.
159
Justas

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

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

ТАК - у вас есть переключатель в ячейке, и он должен скрываться и показать некоторые статические ячейки. Подключите его к 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;
}

И это все. Нажмите на выключатель, и ячейка прячется и появляется снова с Хорошая, плавная анимация.

35
Mohamed Saleh

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

Вот оно:

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];
}

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

Также имейте в виду, что параметр 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];
}
34
henning77
  1. В конструкторе создайте выход для ячеек, которые вы хотите скрыть. Например, вы хотите скрыть 'cellOne', поэтому в viewDidLoad () сделайте это 

cellOneOutlet.hidden = true 

теперь переопределите метод ниже, проверьте, какой статус ячейки скрыт и верните высоту 0 для этих ячеек Это один из многих способов скрыть любую ячейку в статическом 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)
        }

}
13
Saleh Masum

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

11
Austin

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

Демонстрационный проект

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

Суть:

  1. Use tableView:heightForRowAtIndexPath: для динамического определения высоты ячеек в зависимости от состояния.
  2. Когда состояние изменяет отображение/скрытие ячеек, вызывая функцию tableView.beginUpdates();tableView.endUpdates()
  3. Не вызывайте tableView.cellForRowAtIndexPath: внутри tableView:heightForRowAtIndexPath:. Используйте кэшированные indexPaths для дифференциации ячеек.
  4. Не прячьте клетки. Вместо этого установите свойство «Clip Subviews» в Xcode.
  5. Используйте пользовательские ячейки (не простые и т.д.), Чтобы получить приятную анимацию скрытия Также правильно обрабатывайте Auto Layout для случая, когда высота ячейки == 0.

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

10
Sergey Skoblikov

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

Я скрываю ряды на основе состояния переключателя ВКЛ/ВЫКЛ в первом ряду первого раздела. Если переключатель включен, под ним находится 1 ряд в том же разделе, в противном случае есть 2 разных ряда.

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

[[self tableView] reloadData];

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

[cell setHidden:YES];

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

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

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

  • Ряд 0: опция с переключателем ВКЛ/ВЫКЛ
  • Строка 1: отображается, когда опция включена
  • Строка 2: отображается, когда опция выключена
  • Строка 3: отображается, когда опция выключена

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

  • Ряд 0: опция с переключателем ВКЛ/ВЫКЛ
  • Строка 1: отображается, когда опция включена

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

  • Ряд 0: опция с переключателем ВКЛ/ВЫКЛ
  • Строка 1: отображается, когда опция включена 
  • Строка 2: отображается, когда опция выключена
  • Строка 3: отображается, когда опция выключена

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

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

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

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

8
Gareth Clarke

Согласно ответу Юстаса, но для 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)
}
7
Chris Herbst

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

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

  1. Создайте выход для каждой ячейки в статической таблице
  2. Создайте массив только с точками ячеек, чтобы показать
  3. Переопределите cellForRowAtIndexPath, чтобы вернуть ячейку из массива
  4. Переопределите numberOfRowsInSection, чтобы вернуть счетчик массива
  5. Реализуйте метод, чтобы определить, какие ячейки должны быть в этом массиве, и при необходимости вызывайте этот метод, а затем перезагружайте данные.

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

@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
}
3
David Barta

В> 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, как описано выше.

1
CodeOverRide

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

// 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
1
k06a

Простой iOS 11 и IB/раскадровка совместимый метод

Для 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 всякий раз, когда это возможно.

1
robmathers

Ответ в Свифт :

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

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

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

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

1
Federico Zanetello

Хорошо, после некоторых попыток у меня есть необычный ответ .. Я использую переменную 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) }

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

1
Jun Jie Gan

Свифт 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
}
1
pizzamonster

Конечно, вы можете. Сначала верните в таблицу 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
}

Если ваши клетки имеют отличную высоту, верните их тоже:

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

Решение от 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;
}
0
pawel221

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

- (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);
}
0
Vladimir Shutyuk

В дополнение к решению @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)
    }

}

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

0
Luca

Это новый способ сделать это с помощью https://github.com/k06a/ABStaticTableViewController

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