iOS:UITableView reloadData无法正常工作

Spa*_*Dog 2 iphone uitableview uikit iphone-sdk-3.0

我有一个UITableView有两个部分:免费和付费.每个部分都有不同类型的细胞.免费单元格有两个标签和一个图像.付费单元格有两个标签,一个图像和一个允许购买产品的按钮.购买产品后,不得再次显示该特定单元格上的"购买"按钮.说,这就是细胞的初始化方式......

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *IDNormal = @"Normal";
    static NSString *IDComplex = @"Complex";


    if (indexPath.section == 0) { // show free objects  

        UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:IDNormal];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                           reuseIdentifier:IDNormal] autorelease];

            // product description
            UILabel * labelDescription = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 54.0, 225, 18)];
            [labelDescription setTextAlignment:UITextAlignmentLeft];
            [labelDescription setBackgroundColor:[UIColor whiteColor ]];
            [labelDescription setClipsToBounds:YES];
            [labelDescription setFont:[UIFont systemFontOfSize:14.0]];
            [labelDescription setTextColor:[UIColor blackColor]];
            [labelDescription setAlpha:0.6];
            [labelDescription setTag: 860];
            [cell addSubview:labelDescription];
            [labelDescription release];

            // this will show the word FREE on free objects (cells)
            UILabel * labelFREE = [[UILabel alloc] initWithFrame:CGRectMake(235.0, 54.0, 80, 18)];
            [labelFREE setTextAlignment:UITextAlignmentCenter];
            [labelFREE setBackgroundColor:[UIColor greenColor ]];
            [labelFREE setClipsToBounds:YES];
            [labelFREE setFont:[UIFont boldSystemFontOfSize:14.0]];
            [labelFREE setTextColor:[UIColor blackColor]];
            [labelFREE setAlpha:0.75];
            [labelFREE setText:NSLocalizedString(@"freeKey", @"")];     
            [labelFREE setTag: 861];
            [cell addSubview:labelFREE];
            [labelFREE release];

        }


        cell.imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] 
            pathForResource:[NSString stringWithFormat: @"free%d", indexPath.row] ofType:@"jpg"]];      
        NSString * prefixLabel = [NSString stringWithFormat: @"gratis%d", indexPath.row];

        UILabel *labelDescription2 = (UILabel*)[cell viewWithTag:860];
        [labelDescription2 setText:@"FREE"];

        return cell;

    } else { // show paid objects

        UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:IDComplex];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                           reuseIdentifier:IDComplex] autorelease];

            UILabel * labelDescription = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 54.0, 225, 18)];
            [labelDescription setTextAlignment:UITextAlignmentLeft];
            [labelDescription setBackgroundColor:[UIColor whiteColor ]];
            [labelDescription setClipsToBounds:YES];
            [labelDescription setFont:[UIFont systemFontOfSize:14.0]];
            [labelDescription setTextColor:[UIColor blackColor]];
            [labelDescription setAlpha:0.6];
            [labelDescription setTag: 1];
            [cell addSubview:labelDescription];
            [labelDescription release];

        }



        int numberPaidObject = indexPath.row + 500;



        cell.imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] 
            pathForResource:[NSString stringWithFormat: @"table-pg%d", numberPaidObject] ofType:@"jpg"]];       

        NSString * nomeDoProduto = [NSString stringWithFormat: @"paid%d", numberPaidObject];


        if ( NotSoldProduct ) {

            NSString * prefixoEtiqueta = [NSString stringWithFormat: @"paid%d", numberPaidObject];

            UILabel *labelDescription2 = (UILabel*)[cell viewWithTag:1];
            [labelDescription2 setText:[description objectAtIndex: numberPaidObject ];

        }

        return cell;

    }
}
Run Code Online (Sandbox Code Playgroud)

因为我必须确定单击了哪个"购买"按钮,并且我正在使用dequeueReusableCellWithIdentifier,所以我必须使用以下方法...

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

    int numeroOfPaidObject = indexPath.row + 500;

    if ((indexPath.section == 1) && ObjectForSale) {
        // if paid objects and object was not bought yet
        // in theory this section will not be executed if the object was already bought and paid
        // so, I am skipping the BUY button creation and, in theory the cell will not have a BUY
        // button… the problem is that it does... 

        UIButton * buyButton = [[UIButton alloc] initWithFrame:CGRectMake( 235, 45, 80, 30)];
        buyButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
        buyButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
        [buyButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        buyButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
        buyButton.backgroundColor = [UIColor clearColor];
        [buyButton addTarget:self action:@selector(buyNow:) forControlEvents:UIControlEventTouchDown];

        [buyButton setTitle:NSLocalizedString(@"buyKey", @"") forState:UIControlStateNormal]; 

        UIImage *newImage = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] 
                                            pathForResource: @"whiteButton" ofType:@"png"]]
                             stretchableImageWithLeftCapWidth:12.0f topCapHeight:0.0f];

        [buyButton setBackgroundImage:newImage forState:UIControlStateNormal];

        [buyButton setTag: numeroOfPaidObject];
        [cell addSubview:buyButton];

        [buyButton release];
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码的问题是:当我重新加载表的数据时,BUY按钮继续显示在所有单元格上,包括那些已经由用户购买的单元格.

有任何想法吗?

谢谢你的帮助.

Fra*_*itt 7

您可以使用调试器逐步完成它,但这是我的猜测:

由于表格单元格正在被重复使用,因此最终所有已购买的商品最终都存在于之前由未购买商品占据的表格单元格中,因此已经添加了购买按钮.

如果是这种情况,您需要else在第二部分代码中添加一个子句,如果已经购买了产品,则该子句将从单元格中删除该按钮.

另一个问题是,每次显示单元格时,您的代码都会添加一个新按钮,因此很多/大多数单元格中可能都有几个按钮.

您将需要重构代码,以便tableView:cellForRowAtIndexPath:只为新创建的单元格添加一次,按钮.

有两种方法可以做到这一点:

  1. 将"复杂"单元格类型拆分为两种类型:已购买和未购买,并分别创建/出列.仅将按钮添加到未购买的单元格类型.

  2. 将按钮添加到"付费"部分中的所有单元格,并在购买项目时将其隐藏.

无论哪种情况,您都需要一种方法来获取指向按钮的指针.执行此操作的首选方法是使用tag属性,使其成为一个班轮:

UIButton * button = [cell viewForTag:42];
...
Run Code Online (Sandbox Code Playgroud)

您还可以遍历单元格的子视图以查找UIButton对象:

UIButton *button = nil;

foreach (UIView *view in cell.subviews) {
    if ([view isKindOfClass:[UIButton class]])
        button = (UIButton *)view;
}
Run Code Online (Sandbox Code Playgroud)

我建议使用常量标记来标识按钮,然后buyNow:按如下方式重写您的方法:

-(IBAction)buyNow:(id)sender {
    UITableViewCell *cell = (UITableViewCell *)((UIView *)sender).superview;

    int itemID = [tableView indexPathForCell:cell].row + 500;

    ...
}
Run Code Online (Sandbox Code Playgroud)