【问题标题】:IOS: Stop cells being incorrectly reused in UITableViewIOS:停止单元格在 UITableView 中被错误地重用
【发布时间】:2012-06-02 06:23:33
【问题描述】:

我有一个包含四个部分的基本 UITableView。我用一个 Switch 语句控制每个部分的内容。

我以编程方式创建了一个按钮,它应该出现在前三个部分的行中,但不应该出现在第四个部分。但是,该按钮随机出现在第四部分的行中。

我认为这是因为一个单元格正在被重复使用,但是当我使用 Switch 语句创建每个部分的行时,我看不到这是如何发生的。任何想法表示赞赏。

我正在使用这样配置的自定义单元格:`

static NSString *CustomCellIdentifier = @"DashboardCell";

DashboardCell *cell = (DashboardCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];

if (cell == nil) { NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"DashboardCell"
                                                                owner:self options:nil];
    for (id oneObject in nib) if ([oneObject isKindOfClass:[DashboardCell class]])
        cell = (DashboardCell *)oneObject;
}

// Configure the cell.`

创建这个按钮的代码是:`

        button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.frame = CGRectMake(200, 11, 50, 50);        
        UIImage *iConnect = [UIImage imageNamed:@"connect.png"];
        [button setImage:iConnect forState:UIControlStateNormal];
        [button addTarget:self action:@selector(buttonSelected:) forControlEvents:UIControlEventTouchUpInside];
        [cell addSubview:button];`

【问题讨论】:

    标签: ios uitableview uibutton switch-statement cells


    【解决方案1】:

    您需要为每种类型的内容使用不同的重用标识符。所以在这里你有两种类型的内容——有UIButton 的单元格和没有的单元格。

    使用tableView:cellForRowAtIndexPath: 方法的indexPath 选择@"CellWithButton" 或@"CellWithoutButton" 的重用标识符。

    您的代码中实际发生的情况是,所有单元都被赋予了相同的重用标识符,这意味着它们都被放入同一个对象池中。这意味着当您使用[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier]; 时,您正在从这个池中检索一个单元格(其中可能包含没有UIButton 的单元格和有的单元格)。因此,dequeue 方法可以随机返回一个已经添加了UIButton 的单元格。如果您使用两个重用标识符,UITableView 将设置两个对象池,并从每个对象池中正确存放和检索适当的单元格。

    或者您可以使用一个重用池,并在每次使用 dequeue 方法检索一个时检查单元格中的 UIButton

    【讨论】:

    • 谢谢巴哈维尔。我创建了两种细胞类型。像魅力一样工作。
    【解决方案2】:

    在您的 DashboardCell 中,创建一个属性 @property (nonatomic, assign) BOOL buttonEnabled。然后在您的awakeFromNib 中,始终创建按钮并设置button.hidden = YES。覆盖你的属性的设置器

    - (void)setButtonEnabled:(BOOL)enabled {
       buttonEnabled = enabled;
       button.hidden = !enabled;
    }
    

    最后覆盖prepareForReuse

    - (void)prepareForReuse {
       [super prepareForReuse];
       self.buttonEnabled = NO;
    }
    

    现在您可以在方法 cellForRowAtIndexPath 的配置部分中启用/禁用

    【讨论】:

    • 这应该是公认的答案,很容易使用 - (void) prepareForReuse
    【解决方案3】:

    您可以根据部分使用两种不同的单元格标识符。否则,您需要查看从dequeueReusableCellWithIdentifier: 返回的单元格中是否存在按钮,并在必要时添加或删除现有按钮。

    【讨论】:

    • 我要补充一点,您可能只是在旧按钮之上添加新控件,因此尽管您认为它有效,但事实并非如此。这只是你没有在那个按钮上绘制它似乎工作的一次情况。
    • @madmik3 - 你可能是对的,尽管从问题中不清楚按钮创建代码在什么条件下执行。也许它直接跟随或者额外的缩进是有意义的。 [耸肩] :)
    【解决方案4】:

    如果您要重用这些单元格,并且在显示或隐藏每个单元格的按钮背后有一些简单的逻辑,我建议您在 Interface Builder 中创建按钮并将其作为插座连接到您的 UITableViewDelegate。

    然后,我将为单元创建一个设置方法,您可以在任何时间运行任意次数而不会破坏它:

    -(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
    {
        static NSString *CustomCellIdentifier = @"DashboardCell";
    
        DashboardCell *cell = (DashboardCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];
    
        if (cell == nil) { NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"DashboardCell"
                                                                    owner:self options:nil];
            for (id oneObject in nib) if ([oneObject isKindOfClass:[DashboardCell class]])
                cell = (DashboardCell *)oneObject;
        }
    
        // Configure the cell.
        [cell setupWithSomeConfigOptions:someConfigOptions]
    
        return cell;
    }
    

    在您的单元子类中,您将拥有-(void)setupWithSomeOptions:(SomeOptions)someOptions 方法,类似于以下内容:

    -(void)setupWithSomeOptions:(SomeOptions)someOptions
    {
        // some setup code
    
        self.myButtonOutlet.hidden = someOptions.somePropertyToCheckIfButtonShouldBeHidden;
    
        // some more setup code
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-03
      • 1970-01-01
      • 2018-11-27
      • 1970-01-01
      • 2013-07-30
      • 1970-01-01
      相关资源
      最近更新 更多