2011-11-24 53 views
23

该解决方案可能非常简单,但我无法找到它。如何从StoryBoard中设计的UITableView中删除静态单元

使用故事板(iOS 5),我有一个tableViewController,以及一个带有5个部分的设计STATIC tableview,每部分内部都有不同的静态单元格。

我的问题是:如何在viewWillAppear中以编程方式删除单元格?

例如,我设计了一个日期

IBOutlet UITableViewCell * cellForDate; 

和..一个细胞,如果有没有日期,我想删除我的手机。

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

我用尽[tableView deleteRowsAtIndexPaths...]没有工作

任何人有一个想法?

回答

30

试图隐藏单元上映之前,在UITableViewDelegatetableView:willDisplayCell:forRowAtIndexPath:方法中。这是您可以操纵单元格外观的最终方法。但是这不会消除单元格应该占用的空间,因此您可以尝试的另一件事是使用同一协议的tableView:heightForRowAtIndexPath:方法将单元行的高度设置为0。

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

+1

实际上,这是我发现解决问题的唯一方法,使用方法heightForRowAtIndexPath,为IndexPath开关并在此函数中进行验证。如果它是零,我用IBOutlet UITableViewCell引用隐藏单元格,并返回0 ..单元格消失!有20多个细胞时会变得有点令人毛骨悚然,但它效果很好! – Marc

+1

这解决了所有问题https://github.com/xelvenone/StaticDataTableViewController/ –

0

你需要把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]; 
} 
+0

它给我的崩溃错误:** *因未捕获异常'NSInternalInconsistencyException'而终止应用程序,原因:'无效更新:第4节中的行数无效。更新(3)后现有节中包含的行数必须等于该部分在更新之前(3),加上或减去从该部分插入或删除的行数(插入0,删除1),加上或减去移入或移出该部分的行数(移入0,移出0 )“。 – Marc

+0

哦,是的,你需要设置该部分的单元格数量..在你的'tableView:numberOfRowsInSection:'方法中,无论变量是持有行数还是减1,这个方法将返回4而不是5部分(或者很多是必要的)。 – chown

+0

好吧我明白了,我正在尝试一种新的方式,在iOS 5中使用TableViewController来处理故事板和tableview,并且我没有覆盖委托和数据源方法..因为我的数据源是我的故事板中包含的静态表..///////如何使用numberOfRowsInSection来知道我是否刚删除了一行,因为我正在从viewDidAppear方法中删除该行。我应该为每个部分保留一个var,并且只更新我的var? – Marc

-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委托获得的行更新的数目,并且必须是各行之间的正确和/差,当你启动插入/删除,行,当你结束插入/删除

3

如果要永久删除表格单元格,只需拨打deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]并使用与您的行对应的indexPath。您还需要减少由numberOfRowsInSection:返回的行数。然而,我正在寻找一种方法来暂时从静态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; 
} 

的实现代码如下控制器的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; 
} 

and final LY

- (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:(即获得对应于要显示单元格中的存储单元格的行)。

updateSettingsDisplay方法可以保留它的任何类你的tableview控制器上进行调用。如果当它被称为的tableview控制器是不可见的,它只会更新状态,并等到明年成为可见的改变显示的时间。

+0

答案的第二部分看起来不错,但第一段使用'deleteRowsAtIndexPaths'没有效果 –

24

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

- (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的高度有效地从列表中删除。如果细胞不应该隐藏,那么它会从超级获得高度,所以通常发生的任何事情都会发生。

与此唯一的问题是,开始和结束细胞负责在列表或组的顶部和底部的分隔符。所以,如果你隐藏的最后一个单元的一组在该组的底部分频器将略有喜欢它是正常的行而不是全幅的插图。这只是一个问题,如果你隐藏顶部或底部的行,你正在使用分隔线,你关心完全标准的显示。在我的情况下,最好的解决方案就是不要隐藏顶部或底部的行。我将可能隐藏的任何内容移到了组中。或者,您可以接受它不太标准,或禁用桌面上的分隔线。

+0

正如你所说这不完美,因为它创建了一个递归溢出,但是如果你知道你想要隐藏的行和它们的状态,你可以跳过'cellForRowAtIndexPath'调用,它可以很好地工作。 –

+0

@Hola Soy Edu Feliz Navidad我没有看到任何递归。测试iOS 9. –

+0

如果您的cellForRowAtIndexPath以某种方式调用heightForRowAtIndexPath,它只会创建一个递归。这并非不合理,但也不是标准行为。如果您遵循布局的最佳做法,则不应在两处需要高度。 – ima747

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

仅供参考,(想如果我可以评论),如果你是从故事板覆盖分组的静态UITableView的,那么你还需要重写页眉页脚& &意见的高度要修改每节/躲了起来。

我还需要将“GetHeight”方法的返回值设置为零以外的值 - 意味着零值意味着其他值(自动布局或“未设置”等)。

下面的代码是在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); 
    } 
1

斯威夫特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) 
    } 
} 
相关问题