【问题标题】:UITableView discloure indicator going nutsUITableView 披露指标疯了
【发布时间】:2011-11-30 23:39:36
【问题描述】:

我有一个通过 navigationController 推送的 UITableView(在 UIViewController 上)。除了推送之外,我还选择了要填充表格的数组。推送的代码是这样的:

if(self.newView == nil)
{
    NewView *viewTwo = [[NewView alloc] initWithNibName:@"Bundle" bundle:[NSBundle mainBundle]];
    self.newView = viewTwo;
    [viewTwo release];
}

[self.navigationController pushViewController:self.newView animated:YES];
newView.tableArray=newView.arrayWithOptionOne;
[newView.tableView reloadData];

一切正常,每次都会重新加载表格。但是,在第 0 节的最后一行,有一个加载第 1 节的开关。 第 1 部分的最后一行是可点击的(didSelect…),它加载了一个 modalView。在最后一根杆上,我添加了一个披露指示器以及点击时的蓝色背景。表格有滑块、标签等,所以定制的时间比较长:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

UITableViewCell *cell = nil;


static NSString *kDisplayCell_ID = @"DisplayCellID";

cell = [tableView dequeueReusableCellWithIdentifier:kDisplayCell_ID];

if (cell == nil)
    {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:kDisplayCell_ID] autorelease];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    }
else
    {

    UIView *viewToRemove = nil;
    viewToRemove = [cell.contentView viewWithTag:1];
    if (viewToRemove)
        [viewToRemove removeFromSuperview];

    UIView *viewToRemove2 = nil;
    viewToRemove2 = [cell.contentView viewWithTag:2];
    if (viewToRemove2)
        [viewToRemove2 removeFromSuperview];


 }


    if (indexPath.section==0) {
        UIControl *cellValueS = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewKey] objectAtIndex:indexPath.row];
        [cell.contentView addSubview:cellValueS];
    }

    if (indexPath.section==0 && indexPath.row==3) {
        UIControl *cellValueL = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewLabel] objectAtIndex:0] ;
        [cell.contentView addSubview:cellValueL];
    }

    if (indexPath.section==1 && indexPath.row==0){
        UIControl *cellValueS = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewKey] objectAtIndex:indexPath.row] ;
        [cell.contentView addSubview:cellValueS];
    } 

    if (indexPath.section==1 && indexPath.row==1) {
        UIControl *cellValueS = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewKey] objectAtIndex:indexPath.row] ;
        [cell.contentView addSubview:cellValueS];

        UIControl *cellValueL = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewLabel] objectAtIndex:0] ;
        [cell.contentView addSubview:cellValueL];
    }

    if (indexPath.section==1 && indexPath.row==2) {
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
        cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
    }

    return cell;
}

到目前为止还可以。

问题是,当我返回上一个视图并选择另一个选项来填充表格时,当它再次被推送时,我在同一部分的其他行上看到了披露指示器和蓝色选择背景。我观察到这取决于表格的滚动位置。

我试图理解为什么会这样,但我不能。我通过将 newView 设置为 nil 并释放它,然后在它再次被推送之前再次分配它,以某种方式解决了这个问题。

我在这里做错了吗?或者为什么披露指示器和点击背景出现在它们不应该出现的地方?

提前致谢!

开关动作

-(void)extraOptionsSwitchAction:(id)sender{



 switch(extraOptionsSwitch.isOn) {

 case 1:

 // [self.tableView beginUpdates];
 [self.tableView insertSections: [NSIndexSet indexSetWithIndex:1]  withRowAnimation:UITableViewRowAnimationAutomatic];
 [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];

 //[self.tableView reloadData];
 //  [self.tableView endUpdates];

 break;

 case !1:

 //   [self.tableView beginUpdates];
 [self.tableView deleteSections: [NSIndexSet indexSetWithIndex:1]  withRowAnimation:UITableViewRowAnimationAutomatic];
 // [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];

 [self.tableView reloadData];
 // [self.tableView endUpdates];

 break;

 }
 }

【问题讨论】:

    标签: iphone ios uitableview uinavigationcontroller


    【解决方案1】:

    这与重复使用单元格有关。您可能不会在您的细胞创建方法中区分不同的细胞类型 - 因此屏幕外的一个细胞可以轻松地用于另一个(不同类型)细胞。此外,您似乎一遍又一遍地添加子视图 - 仅在实例化单元格(使用 alloc/int)时才这样做,而不是在配置时。

    另外,对于不同的细胞类型,使用不同的标识符(您没有显示此代码)。

    编程指南在表格视图及其单元格和重用模式方面提供了很好的示例。值得多读几遍 - 很容易出错,是性能调优的主要主题。

    编辑

    现在您添加了更多代码,另一个问题似乎在这里:

    if (indexPath.section==1 && indexPath.row==2) {
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
        cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
    }
    

    您缺少else 部分。 selectionStyleaccessoryType 设置为之前设置的值 - 您错过了为除该特殊单元之外的所有其他单元正确配置单元。

    不过,每种单元格类型都应该有自己的标识符。如果子视图的添加/删除按预期工作,很难从该代码中分辨出来。

    一个想法:由于您在这里并没有真正重用很多单元格,因此您甚至可以通过更改来禁用重用

    static NSString *kDisplayCell_ID = @"DisplayCellID";
    cell = [tableView dequeueReusableCellWithIdentifier:kDisplayCell_ID];
    

    static NSString *kDisplayCell_ID = nil;
    

    这总是会产生一个新的细胞。不过,在一般情况下,我不建议这样做。

    【讨论】:

    • +1 - 总的来说,所有的编程指南都写得很好,值得一读。
    • @Eiko 我为该方法添加了整个代码。我实际上使用了 Apple 自己的示例代码作为参考。如果我必须在一个单元格上添加两个不同的子视图,我会注意它们具有不同的标签,以便它们在屏幕外时都会被释放。此外,我添加的子视图没有任何问题,只是显示指示器和点击背景。如果我添加一堆子视图,那是因为在一行中有一个带有标签的 Slider 指示其值,在下一行我只需要一个 textField 等。
    • 现在我再次检查了它,它与滚动没有任何关系。似乎它与推送视图时加载的数组有关。当我返回并再次推动 arrayOne 或 arrayThree 时,我会看到第二行和第三行的披露。如果我推动数组二,我会在三行上看到公开指示符。这些数组包含两个 NSdictionaries,一个用于 Section==0,一个用于 section==1。有趣的是 section==1 对他们来说都是一样的。
    • 我相信我知道问题出在哪里。它发生在我启动我的汽车引擎去工作时。我讨厌那个。我认为带有披露指示符和点击背景的条件语句应该在单元格的分配下,其中声明了其他单元格的行为。现在我将不得不等待 10 多个小时才能确定我是否正确。戴上帽子!
    • @Eiko 我知道代码不是很清楚,但 subViews 工作得很好。尽管它有效,但我想重写它以使其更清晰,以供我将来参考。所以,如果我正确理解你的答案,那么今天早上的想法是正确的。不是吗。。您能否详细说明“一个单元标识符”是什么意思?
    【解决方案2】:

    这是由于cellReusability,长期以来,它浪费了很多开发人员的时间和精力。如果您了解单元格可重用性的概念,您就会知道在滚动时,行和节的索引保持不变(尽管您希望 uiTableView 上的不同位置它会有所不同)。

    唯一的方法是subClassUITableViewCell 并创建您自己的CustomUITableViewCell,并使用披露指示器实现它,或者拒绝您对仅适合屏幕的小TableView 的输入并制作scrollable = NO

    【讨论】:

      猜你喜欢
      • 2016-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      相关资源
      最近更新 更多