如何从StoryBoard中设计的UITableView中删除静态单元格

时间:2011-11-24 20:39:42

标签: iphone uitableview storyboard

解决方案可能非常简单,但我无法找到它......!

使用storyboard(iOS 5),我有一个tableViewController,以及一个设计有5个部分的STATIC表视图,每个部分内都有不同的静态单元格。

我的问题是:如何在viewWillAppear

中以编程方式删除单元格

例如,我有一个为日期设计的单元格

IBOutlet UITableViewCell * cellForDate;

并且..如果没有日期,我想删除我的单元格。

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

我已尝试[tableView deleteRowsAtIndexPaths...]无效

有人有个主意吗?

9 个答案:

答案 0 :(得分:33)

尝试在UITableViewDelegate的{​​{3}}方法中隐藏单元格。这是你可以操纵细胞外观的最终方法。但是这不会删除单元格应该占用的空间,因此您可以尝试的另一件事是使用相同协议的tableView:willDisplayCell:forRowAtIndexPath:方法将单元格行的高度设置为0。

另一种最健壮的方法是设计一种方法,用于确定是否需要该部分中的日期单元格,并根据结果返回该部分中的正确行数,并返回其他部分行单元格把这种情况考虑在内。然后在viewWillAppear上重新加载tableView的数据。

答案 1 :(得分:26)

希望这是一个通用解决方案,但它仍然不完美

- (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的高度,有效地将其从列表中删除。如果不应该隐藏单元格,那么它将从超级中获得高度,因此通常会发生任何事情。

唯一的问题是,开始和结束单元格负责列表或组顶部和底部的分隔符。因此,如果隐藏组中的最后一个单元格,则组中的底部分隔符将略微像在正常行而不是全宽度上一样。如果您隐藏顶行或底行并且您正在使用分隔符并且您关心完全标准显示,则这只是一个问题。在我的情况下,最好的解决方案是不隐藏顶行或底行。我将可能隐藏的任何内容移动到组的中间。或者你可以接受它不是很标准,或者禁用你桌子上的行分隔符。

答案 2 :(得分:11)

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 :(得分:3)

如果要永久删除tableview单元格,只需使用与您的行对应的indexPath调用deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]。您还需要减少numberOfRowsInSection:返回的行数。

但是,我正在寻找一种从静态tableview中暂时“删除”不需要的静态tableview单元格的方法,因为我希望有时会有一个特定的行,有时则不需要。我还希望能够从tableview控制器外部按需更新。

我的情况相当简单,因为它是显示或隐藏的第一行。您可以概括以满足您自己的需求。我的tableview控制器是我的数据源委托。

首先,我在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;
}

tableview控制器的viewDidLoad如下所示:

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

tableview的数据源代理:

- (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]中可用 - 所以使用它来永久存储静态tableview单元格。然后根据需要调整行数,并在tableview委托的cellForRowAtIndexPath:中正确映射行(即,获取与要显示的单元格对应的存储单元格的行)。

可以通过任何保留它的类在您的tableview控制器上调用updateSettingsDisplay方法。如果在调用tableview控制器时看不到它,它只会更新状态并等到下次可见时更改显示。

答案 4 :(得分:1)

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

答案 5 :(得分:0)

你可能想看看这个

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

答案 6 :(得分:0)

FYI(如果可以,我会评论),如果你从故事板上覆盖了一个Grouped静态UITableView,那么你还需要覆盖Header&amp;页脚视图&amp;您正在修改/隐藏的每个部分的高度。

我还需要为&#34; GetHeight&#34;设置返回值。除零以外的其他方法 - 暗示零值意味着其他东西(autolayout,或#34;未设置&#34;或类似)。

以下代码位于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);
    }

答案 7 :(得分:-1)

您需要在删除调用之前放置beginUpdates并在{:1}}之后放置:

endUpdates

回应你的评论:

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

答案 8 :(得分:-1)

// 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委托来获取更新的行数,它必须是启动插入/删除时行之间的正确总和/差异以及结束插入时的行/删除