IOS:维护uitableviewcell中的按钮状态

时间:2012-02-23 23:31:41

标签: ios uitableview uibutton

我有一个iPhone应用程序问题一直困扰着我几天,看起来真的不应该这么难,所以我肯定我错过了一些明显的东西。我已经研究过很多关于“类似”主题的论坛讨论,但没有任何实际解决这个问题的内容,特别是。

要明确的是,如果有一些文件或其他一些我应该研究的来源,请指出我正确的方向。

这里......

我有一个项目列表,我在表格中向用户显示(uitableview)。每个项目的单元格(uitableviewcell)是自定义的,包含图像和Like按钮(uibutton)。正如所料,对于表中的每个项目,用户可以单击“赞”按钮或忽略它。 like按钮调用单独的进程来更新服务器。简单,对吧?

所以,问题在于:

当在特定单元格上单击“赞”按钮时,“选定”状态正常工作,但是当您将单元格滚出视图时,表格中的其他随机单元格将“相似”按钮显示为“已选择”,即使它们从未被触摸过。因为细胞被重复使用,出于明显的性能原因,我理解为什么会发生这种情况。我不明白的是为什么我的方法(见下面的代码)不会像我认为的那样覆盖或重置按钮的状态。为简洁起见,我只在此处包含相关代码(希望格式正确):

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"MyCustomCell";
    MyCustomViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {
    cell = [[MyCustomViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
}

    NSString *myRating = [[self.dataArray objectAtIndex:indexPath.row] valueForKey:@"my_rating"];

    // Create the Like button
    UIButton *likeButton = [[UIButton alloc] initWithFrame:CGRectMake(260, 68, 40, 40)];
    [likeButton setImage:[UIImage imageNamed:@"thumbsUp"] forState:UIControlStateNormal];
    [likeButton setImage:[UIImage imageNamed:@"thumbsUpSelected"] forState:UIControlStateSelected];
    if (myRating == @"9") {
        [likeButton setSelected:YES];
    }
    [likeButton setTitle:@"9" forState:UIControlStateNormal];
    [likeButton setTag:indexPath.row];
    [cell.contentView addSubview:likeButton];
    [likeButton addTarget:self action:@selector(likeButtonPressed:) forControlEvents:UIControlEventTouchUpInside];

    return cell;
}

- (void)likeButtonPressed:(UIButton *)sender {

    // Changed the Selected state on the button
    UIButton *button = (UIButton *)sender;
    button.selected = !button.selected;

    // Create a new object with the user's rating and then replace it in the dataArray
    NSString *ratingText = sender.titleLabel.text;    
    NSMutableArray *myMutableArray = [[self.dataArray objectAtIndex:row] mutableCopy];
    [myMutableArray setValue:ratingText forKey:@"my_rating"];
    [self.dataArray replaceObjectAtIndex:row withObject:myMutableArray];
}

所以,我经历了很多迭代,但我似乎无法获得按钮的状态来显示那些喜欢的项目的选定图像并保留那些尚未被删除的项目的正常图像喜欢。

非常感谢任何帮助或建议。

3 个答案:

答案 0 :(得分:9)

有一个简单的方法。你可以欺骗按钮以保持最新的选择状态。

制作一个可变数组,以保持按钮的选定状态

selectedButton = [[NSMutableArray alloc]init];//i've already defined the array at the .h file

for (int i = 0; i<yourTableSize; i++) //yourTableSize = how many rows u got
{
    [selectedButton addObject:@"NO"];
}

在tableviewcell方法中,声明你的按钮并设置它以便它引用mutablearray来设置它的选择状态

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) 
{ 
    cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
}

UIImage *img = [UIImage imageNamed:@"btn_unselected.png"];
UIButton *toggleButton = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, img.size.width, img.size.height)];
[toggleButton setImage:img forState:UIControlStateNormal];
img = [UIImage imageNamed:@"btn_selected.png"];
[toggleButton setImage:img forState:UIControlStateSelected];
[toggleButton setTag:indexPath.row+100];//set the tag whichever way you wanted it, i set it this way so that the button will have tags that is corresponding with the table's indexpath.row
[toggleButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:toggleButton];

//and now we set the button's selected state, everytime the table reuse/redraw the cell the button will set it's selected state according to the array

if([[selectedButton objectAtIndex:indexPath.row]isEqualToString:@"NO"])
{
    [toggleButton setSelected:NO];
}
else 
{
    [toggleButton setSelected:YES];
}

return cell;

最后,创建按下按钮时按钮触发的方法,以更改其选择状态

-(void)buttonPressed:(UIButton*)sender
{
    int x = sender.tag - 100; //get the table's row
    if([sender isSelected]) //if the button is selected, deselect it, and then replace the "YES" in the array with "NO"
    {
        [selectedButton replaceObjectAtIndex:x withObject:@"NO"];
        [sender setSelected:NO];
    }
    else if (![sender isSelected]) //if the button is unselected, select it, and then replace the "NO" in the array with "YES"
    {
        [selectedButton replaceObjectAtIndex:x withObject:@"YES"];
        [sender setSelected:YES];
    }
}

答案 1 :(得分:4)

问题在于,每次创建或重复使用单元格时,都会给它一个新的类似按钮,所以当你重复使用类似按钮被激活的单元格时,你会给它一个停用的按钮,但是旧的,激活的按钮仍然存在。

不是每次需要单元格时都创建类似按钮,而应该只设置现有类似按钮的状态。请参阅this question的答案,了解处理该问题的一些可能方法。

答案 2 :(得分:1)

这是无效的(至少如果你试图比较字符串我的内容而不是地址):

if (myRating == @"9")

试试这个:

if ([myRating isEqualToString:@"9"])

并且注意到多个按钮的创建,以及+1到yuji。