Как удалить статическую ячейку из UITableView, разработанного в StoryBoard - PullRequest
25 голосов
/ 25 ноября 2011

Решение, вероятно, очень простое, но я не смог его найти ..!

Работая с раскадровкой (iOS 5), у меня есть tableViewController и разработанный STATIC табличный вид с 5 разделами, с различными статическими ячейками внутри каждого раздела.

Мой вопрос: как программно удалить ячейку в viewWillAppear?

Например, у меня есть ячейка, предназначенная для даты

IBOutlet UITableViewCell * cellForDate;

И .. если нет даты, я хочу удалить свою клетку.

cellForDate.hidden = true; //Hide the cell, but leave a blank space

Я пытался [tableView deleteRowsAtIndexPaths...] не работал

Кто-нибудь получил идею?

Ответы [ 9 ]

33 голосов
/ 25 ноября 2011

Попробуйте скрыть ячейку перед ее отображением в методе UITableViewDelegate tableView:willDisplayCell:forRowAtIndexPath:. Это последний метод, где вы можете управлять внешним видом клетки. Это, однако, не удалит пространство, которое должна занимать ячейка, поэтому вы можете попытаться установить высоту строки ячейки равной 0, используя метод tableView:heightForRowAtIndexPath: того же протокола.

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

26 голосов
/ 18 февраля 2014

Надеюсь, это немного более универсальное решение, но оно все еще не идеально

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

С помощью этого метода вы устанавливаете скрытую ячейку, связанную с IBOutlet, а затем, когда таблица пытается отобразить строку, она сначала проверяет, должна ли быть скрыта ячейка (использующая супер-вызов для получения ячейки), если так он возвращает высоту 0, которая эффективно удаляет его из списка. Если ячейка не должна быть скрыта, она получает высоту от супер, поэтому все, что обычно происходит, все равно происходит.

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

11 голосов
/ 12 июля 2017

Swift 3

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if indexPath.section == 0 {
        cell.isHidden = true
    }
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.section == 0 {
        return 0
    } else {
        return super.tableView(tableView, heightForRowAt: indexPath)
    }
}
3 голосов
/ 28 июня 2013

Если вы хотите навсегда удалить ячейку таблицы, просто вызовите deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone] с indexPath, соответствующим вашей строке. Вам также нужно уменьшить число возвращаемых строк на numberOfRowsInSection:.

Однако я искал способ временно «удалить» ненужные статические ячейки табличного представления из статического табличного представления, потому что я хотел, чтобы определенная строка была там иногда, а иногда нет. Я также хотел иметь возможность обновлять это по требованию извне контроллера tableview.

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

Сначала я создал открытый метод в контроллере табличного представления для обновления переменных состояния и запуска повторного отображения:

- (void)updateSettingsDisplay:(BOOL)hideSetting
{
    if (hideSetting == self.hideSetting) {
        return; // no need to do anything because it didn't change
    }

    self.hideSetting = hideSetting;
    self.numRows = (hideSetting)? kNumRowsWithSetting : kNumRowsWithoutSetting;

    // redisplay only if we're visible
    if (!self.viewJustLoaded && (self.navController.visibleViewController == self)) {
        [self.tableView reloadData];
    }
    self.viewJustLoaded = NO;
}

Контроллер таблицы 101 * * выглядит следующим образом:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // check whether or not to display out-of-coverage tableview cell
    self.hideSetting = YES; // initial value; could just as easily be NO
    self.viewJustLoaded = YES;
    [self updateSettingsDisplay];
}

Делегат источника данных таблицы просмотра:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return self.numRows;
}

и наконец

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // set row to the index of the stored tableView cell that corresponds to the
    // cell you want (its location in the static tableview from your storyboard)
    NSInteger row = indexPath.row;
    if (self.hideSetting) {
        // skip drawing setting's tableviewcell (since the setting we're hiding is
        // first, we can just increment the row to get the one we want)
        ++row;
        assert(row < kTotalRows); // bounds checking just to convince yourself (remove after testing)
    }
    // get a new index path since the row field is read-only
    NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section];

    // grab the cell from super that corresponds to the cell you want
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:newIndexPath]; // static table

    return cell;
}

Хитрость в том, что статические ячейки всегда доступны в [super tableView:tableView cellForRowAtIndexPath:newIndexPath] - так что используйте это для постоянного хранения ваших статических ячеек таблицы. Затем отрегулируйте количество строк по мере необходимости и правильно сопоставьте строки (т. Е. Получите строку сохраненной ячейки, которая соответствует ячейке, которую вы хотите отобразить) в делегате табличного представления cellForRowAtIndexPath:.

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

1 голос
/ 03 октября 2015
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

    if(indexPath.section == 1) { //For example
        return 0
    }
}

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    if(indexPath.section == 1) {
         cell.hidden = true
    }
}
0 голосов
/ 18 июля 2016

К вашему сведению (прокомментировал бы, если бы я мог), если вы переопределяете сгруппированный статический UITableView из раскадровки, то вам также необходимо переопределить представления и высоты верхнего и нижнего колонтитула для каждого раздела, который вы изменяете / скрываете.

Мне также нужно было установить возвращаемое значение для методов «GetHeight» на что-то отличное от нуля, подразумевая, что нулевое значение означает что-то еще (autolayout, или «not set» или подобное).

Приведенный ниже код написан на Xamarin iOS C #, но напрямую переводится в соответствующие методы Obj-C:

    public override void WillDisplayHeaderView(UITableView tableView, UIView headerView, nint section)
    {
        if (section == 0)
        {
            headerView = new UIView(new CGRect(0,0,0,0));
        }
    }

    public override nfloat GetHeightForHeader(UITableView tableView, nint section)
    {
        if (section == 0)
        {
            return 1f;
        }
        return base.GetHeightForHeader(tableView, section);
    }

    public override void WillDisplayFooterView(UITableView tableView, UIView footerView, nint section)
    {
        if (section == 0)
        {
            footerView = new UIView(new CGRect(0, 0, 0, 0));
        }
    }

    public override nfloat GetHeightForFooter(UITableView tableView, nint section)
    {
        if (section == 0)
        {
            return 1f;
        }
        return base.GetHeightForFooter(tableView, section);
    }
0 голосов
/ 18 октября 2013

вы можете посмотреть на это

https://github.com/xelvenone/StaticDataTableViewController/

использование

self.hideSectionsWithHiddenRows = YES; //YES, NO
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
0 голосов
/ 16 марта 2012
// just authed with facebook, and I want to delete the first 3 rows of my 4 row table that are no longer necessary    
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
    if(wantsFacebook)
        return 1;

    return 4;
}

После фиксации обновлений tableView вызовет делегат numberOfRowsInSection для получения обновленного количества строк, и он ДОЛЖЕН быть правильной суммой / разницей между строками, когда вы начали вставку / удаление, и строками, когда вы заканчивали вставку / удалить

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

Вам необходимо поставить beginUpdates перед вызовом удаления и endUpdates после:

[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:r inSection:s]]];
[tableView endUpdates];

В ответ на ваш комментарий:

- (NSInteger)tableView:(UITableView)tableView numberOfRowsInSection:(NSInteger)section {
    NSInteger ret;
    switch (section) {
        case 0:
            // sectionZeroRows doesnt have to be a 
            // property (an attribute works just fine), but it
            // helps with explaining this example.
            ret = self.sectionZeroRows;
            break;
        // ...
    }
    return ret;
}

- (void)someMethod {
    --self.sectionZeroRows;
    [tableView beginUpdates];
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]]];
    [tableView endUpdates];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...