UITableView设置为静态单元格。是否可以通过编程方式隐藏一些单元格?

时间:2011-11-24 16:46:41

标签: ios objective-c uitableview

UITableView设置为静态单元格。

是否可以通过编程方式隐藏部分单元格?

22 个答案:

答案 0 :(得分:160)

隐藏UITable中的静态单元格:

  1. 添加此方法
  2. 在UITableView控制器委托类中:

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

    夫特:

    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中。

答案 1 :(得分:48)

您正在寻找此解决方案:

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的hacky解决方案,并允许您设置更改动画并隐藏整个部分

答案 2 :(得分:35)

最好的方法如下面的博客所述 http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/

  

在界面构建器中正常设计静态表视图 -   完成所有可能隐藏的细胞。但是你有一件事   必须为你想要隐藏的每个潜在细胞做 - 检查   单元格的“剪辑子视图”属性,否则为内容   当你试图隐藏它时,细胞不会消失(通过收缩它   身高 - 以后再说。)

     

所以 - 你在一个单元格中有一个开关,开关应该隐藏   并显示一些静态细胞。将它连接到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;
}
     

就是这样。翻转开关,细胞隐藏并重新出现   漂亮,流畅的动画。

答案 3 :(得分:34)

我的解决方案与Gareth的方向类似,不过我做了不同的事情。

这里是:

<强> 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

还要记住,像didSelectRowAtIndexPath:这样的方法的indexPath参数对于同一个单元格会有所不同,具体取决于状态(即隐藏的单元格数)。因此,始终偏移任何indexPath参数并使用这些值可能是个好主意。

<强> 2。动画更改

正如Gareth已经说过的那样,如果使用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];
}

答案 4 :(得分:13)

  1. 在设计器中,为要隐藏的单元格创建一个插座。例如,您想要隐藏&#39; cellOne&#39;,所以在viewDidLoad()中执行此操作
  2. cellOneOutlet.hidden = true

    现在覆盖以下方法,检查隐藏了哪个单元格状态,并为这些单元格返回高度0。这是您可以在swift中隐藏静态tableView中的任何单元格的众多方法之一。

    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)
            }
    
    }
    

答案 5 :(得分:11)

我想出了一个实际隐藏部分并且不删除部分的替代方法。我尝试了@ 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数组,添加它,它将隐藏正确的部分。隐藏行有点棘手,但可能。如果我们使用分组的UITableView,我们不能只将我们要隐藏的行的高度设置为0,因为边框将无法正确绘制。

答案 6 :(得分:10)

事实证明,您可以在静态UITableView中隐藏和显示单元格 - 以及动画。并不难实现。

Demo project

Demo project video

要点:

  1. Use tableView:heightForRowAtIndexPath:根据某些状态动态指定单元格高度。
  2. 当状态通过调用tableView.beginUpdates();tableView.endUpdates()
  3. 更改显示/隐藏的动画单元格时
  4. 请勿在{{1​​}}内拨打tableView.cellForRowAtIndexPath:。使用缓存的indexPaths来区分单元格。
  5. 不要隐藏细胞。设置&#34;剪辑子视图&#34; Xcode中的属性。
  6. 使用自定义单元格(不是Plain等)来获得漂亮的隐藏动画。此外,在单元格高度== 0的情况下正确处理自动布局。
  7. More info in my blog (Russian language)

答案 7 :(得分:8)

是的,这绝对是可能的,尽管我现在正在努力解决同样的问题。我已经设法让细胞隐藏起来,一切正常,但我目前无法整齐地制作动画。这是我发现的:

我根据第一部分第一行中ON / OFF开关的状态隐藏行。如果开关打开,则同一部分下方有1行,否则有2行不同。

切换开关时调用了一个选择器,并设置了一个变量来指示我所处的状态。然后我调用:

[[self tableView] reloadData];

我覆盖 tableView:willDisplayCell:forRowAtIndexPath:函数,如果该单元格应该被隐藏,我会这样做:

[cell setHidden:YES];

隐藏单元格及其内容,但不会删除它占用的空间。

要删除空格,请覆盖 tableView:heightForRowAtIndexPath:函数,并为应隐藏的行返回0。

您还需要覆盖 tableView:numberOfRowsInSection:并返回该部分中的行数。你必须在这里做一些奇怪的事情,这样如果你的桌子是一个分组的样式,圆角就会出现在正确的单元格上。在我的静态表中,该部分有完整的单元格集,因此第一个单元格包含该选项,然后是1个单元格用于ON状态选项,另外2个单元格用于OFF状态选项,总共4个单元格。当选项为ON时,我必须返回4,这包括隐藏选项,以便显示的最后一个选项有一个圆角框。当选项关闭时,最后两个选项不会显示,所以我返回2.这一切都让人觉得笨重。对不起,如果这不是很清楚,描述起来很棘手。为了说明设置,这是IB中表格部分的构造:

  • 第0行:带ON / OFF开关的选项
  • 第1行:选项开启时显示
  • 第2行:选项关闭时显示
  • 第3行:选项关闭时显示

因此,当选项为ON时,表格会报告两行:

  • 第0行:带ON / OFF开关的选项
  • 第1行:选项开启时显示

当选项为OFF时,表格将报告四行:

  • 第0行:带ON / OFF开关的选项
  • 第1行:选项开启时显示
  • 第2行:选项关闭时显示
  • 第3行:选项关闭时显示

这种方法感觉不正确有几个原因,就目前为止我的实验而言,所以如果你找到更好的方法,请告诉我。到目前为止我所观察到的问题是:

  • 告诉表格行数与基础数据中可能包含的行数不同,这是错误的。

  • 我似乎无法为变化制作动画。我尝试使用 tableView:reloadSections:withRowAnimation:而不是reloadData,结果似乎没有意义,我仍然试图让这个工作。目前似乎发生的事情是tableView没有更新正确的行,所以一个仍然隐藏应该显示,并在第一行下面留空。我认为这可能与关于基础数据的第一点有关。

希望有人能够建议替代方法或者如何扩展动画,但也许这会让你开始。我对缺少功能的超链接表示歉意,我把它们放进去但是被垃圾邮件过滤器拒绝了,因为我是一个相当新的用户。

答案 8 :(得分:7)

根据Justas的回答,但是对于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)
}

答案 9 :(得分:3)

由于自动布局问题,隐藏/显示单元格,更改rowHeight或混乱使用自动布局约束的上述答案对我不起作用。代码变得无法容忍。

对于一个简单的静态表,最适合我的是:

  1. 为静态表格中的每个单元格创建一个出口
  2. 仅使用要显示的单元格的出口创建一个数组
  3. 覆盖cellForRowAtIndexPath以从数组中返回单元格
  4. 覆盖numberOfRowsInSection以返回数组的计数
  5. 实现一个方法来确定该数组中需要的单元格,并在需要时调用该方法,然后重新加载数据。
  6. 以下是我的表视图控制器的示例:

    @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
    }
    

答案 10 :(得分:2)

好的,经过一番尝试,我得到了一个不常见的答案。 我正在使用“ 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) }

这将减少委托方法中的逻辑,并且您只需要关注您的业务需求。

答案 11 :(得分:1)

回答 swift

在TableViewController中添加以下方法:

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

如果tableView尝试绘制您想要隐藏的单元格,那么它将不会显示它,因为它的高度将设置为0pt,这要归功于上面的方法,其他所有内容都保持不变。

请注意indexPathOfCellYouWantToHide可以随时更改:)

答案 12 :(得分:1)

在&gt; 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,如上所述。

答案 13 :(得分:1)

简单的iOS 11&amp; IB /故事板兼容方法

对于iOS 11,我发现Mohamed Saleh's answer的修改版本效果最好,并根据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)
}

您需要确保cellIsHiddenindexPathOfHiddenCell已根据您的使用情况进行了适当设置。对于我的代码,它们是我的表视图控制器上的属性。

切换单元格

以任何方法控制可见性(可能是按钮操作或didSelectRow),在performBatchUpdates块内切换cellIsHidden状态:

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

Apple recommends performBatchUpdates over beginUpdates/endUpdates,只要有可能。

答案 14 :(得分:1)

斯威夫特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
}

答案 15 :(得分:1)

我找到了一种在静态表格中隐藏单元格动画的解决方案。

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

关于UISwitch价值变化的一项IBAction:

- (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

答案 16 :(得分:0)

当然可以。首先,返回你想要显示的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))
}

答案 17 :(得分:0)

来自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;
}

答案 18 :(得分:0)

这是使用https://github.com/k06a/ABStaticTableViewController

执行此操作的新方法
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]

答案 19 :(得分:0)

对于在表格视图的最底部隐藏单元格的最简单方案,您可以在隐藏单元格后调整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);
}

答案 20 :(得分:0)

除了@Saleh Masum解决方案:

如果您收到自动布局错误,则可以从tableViewCell.contentView

中删除约束

斯威夫特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)
    }

}

解决方案取决于您应用的流程。如果要在同一个视图控制器实例中显示/隐藏单元格,这可能不是最佳选择,因为会删除约束

答案 21 :(得分:0)

我有一种更好的方法来隐藏静态单元格甚至动态部分,而不会受到任何黑客攻击。

将行高设置为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个高度。

此代码也非常易于维护。例如,如果您要添加/删除更多的单元格或部分。

类似地,您可以创建节标题标题数组和节脚标题数组来动态配置节标题。