操蛋的UITableView重用机制

1,背景

你可能会遇见一下情况:

使用UITableView加载数据,比如你的每一个cell上面有一个UITextField,当你在第一个cell的UITextField中写下了内容,开始下滑UITableView,你会发现由于UITableView重用机制的影响,你的第一个UITextField的值会发生变化,令人费解啊,抓狂!

之类的情况可能很多,下面咱们就总结一下发生这种情况的原因,针对这种原因,咱们找到对应的解决办法。

2,用自己的话说UITableView的重用机制

当遇见这中情况的时候,我问过好多个ios程序员,他们多数的解决办法是直接不让它重用了,当然了,这样的话,表面上确实解决了问题,但是却给自己的程序带来了很大的隐患。我们做东西,应该去想着做最好的东西出来,不能这样草草的应付。

好了,言归正传。

所谓重用机制,就是模板共用一套,换的是内容。比如;view上显示七个cell,当第一个cell消失,第八个cell出现,那么第八个cell用的还是第一个cell,只不过他把第一个cell的内用换成了自己的。这就是重用的原理。问题就出现在他在换内容的时候,没换好,就出现了错误。

那么为什么会出现这种错误呢,为什么我们替换内容的时候根本就没有错,重用后还会出现错误呢?

不说废话 直接说我遇见的问题以及我的解决办法:

我的问题是右边的UITableView在上下滑动的时候按钮出现了重用,点过之后的按钮会发生变化,分成两个按钮,一个加菜按钮一个减菜按钮

当我点了第一个cell后,分裂成功,我将UITableView向下滑,却出现了第一个cell的按钮又变回了原型。

出现的原因:这个cell是我自定义的,这个按钮的状态是没有记录的,一次重用后他会和原来的状态一样。

解决办法:我是这样想的解决办法,之所以个重用是因为第一个和第八个没有特别的标注,我必须想一个区分第一个和第八个的属性,那么就有了indexpath.row,一位他们即使在重用这个值也不会相同,因此我们就用这个属性解决这个操蛋的问题。

好了,原理是这样,来看看我的解决代码吧;

 

  [self.dataArr enumerateObjectsUsingBlock:^(NSDictionary * obj, NSUInteger idx, BOOL *stop) {
        [self.tempDotNumberDic setValue:[obj valueForKey:@"number"] forKey:[obj valueForKey:@"ProID"]];
    }];

说明:dataArr是tableview的数据源,tempDotNumberDic是一个记录点菜份数的字典,他的key是点菜id(因为id是唯一的,这样可以区分开),他的value是点菜份数。

 

 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (tableView.tag == 100)
    {
        static NSString * strMark = @"cellMark";
        DishesClassCell * cell = [tableView dequeueReusableCellWithIdentifier:strMark];
        if (cell == nil)
        {
            cell = [[DishesClassCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strMark];
        }
        if (indexPath.row<self.myClassArr.count)
        {
            cell.textContentLab.text = [[self.myClassArr objectAtIndex:indexPath.row] valueForKey:@"ClassName"];
        }
        if (self.tempClassDic.count>0)
        {
            NSString * result = [self.tempClassDic valueForKey:[NSString stringWithFormat:@"%d",indexPath.row]];
            if ([result isEqualToString:@"1"])
            {
                cell.backgroundImageView.image = [UIImage imageNamed:@"DishClass06.png"];
            }
            else
            {
                cell.backgroundImageView.image = [UIImage imageNamed:@"DishClass05.png"];
            }
        }
        return cell;
    }
    
    NSString *str1 = [NSString stringWithFormat:@"cellmark%d",selectRow];
    NSString * strMark1 = str1; //不停类别用不同的重用标示符,目的是为了不同分类同一位置的重用现象。
    DishesDetailListCell * cell1 = [tableView dequeueReusableCellWithIdentifier:strMark1];
    __block int dotNumber = 0;
    if (indexPath.row < self.myProArr.count)
    {
        __block NSString * proID;
        NSString * currID = [[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"ProID"];
        [self.dataArr enumerateObjectsUsingBlock:^(NSDictionary * obj, NSUInteger idx, BOOL *stop) {
            proID = [obj valueForKey:@"ProID"];
            if ([currID isEqualToString:proID])
            {
                dotNumber = [[[[DataBase selectNumberFromProId:[currID intValue]] objectAtIndex:0] valueForKey:@"number"] intValue];
            }
        }];
    }
    
    if (cell1 == nil)
    {
        cell1 = [[DishesDetailListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strMark1 andDotNumber:dotNumber];
    }
    cell1.dishView.myLab.text = [NSString stringWithFormat:@"点%d份",dotNumber];
    int resylt = [[self.tempDotNumberDic valueForKey:[[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"ProID"]] intValue];
    if (resylt == 0)
    {
        [cell1.dishView zeroState];
    }
    else
    {
        [cell1.dishView initView:resylt];
    }
    if (indexPath.row%2 == 0)
    {
        cell1.backgroundImageView.image = [UIImage imageNamed:@"5.png"];
    }
    else
    {
        cell1.backgroundImageView.image = [UIImage imageNamed:@"6.png"];
    }
    cell1.selectionStyle=UITableViewCellSelectionStyleNone;
    cell1.selectedBackgroundView = [[UIView alloc] initWithFrame:cell1.frame];
    cell1.titleLab.text = [[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"ProName"];
    NSString * str = @"¥";
    NSString * priceStr = [[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"prices"];
    cell1.priceLab.text = [str stringByAppendingFormat:@"%@",priceStr];
    cell1.dishView.price = [priceStr doubleValue];
    cell1.dishView.index = indexPath.row;
    
    [cell1.dishView.rightButton addTarget:self action:@selector(rightButtonClickEvent:) forControlEvents:UIControlEventTouchUpInside];
    [cell1.dishView.leftButton addTarget:self action:@selector(leftButtonClickEvent:) forControlEvents:UIControlEventTouchUpInside];
    [cell1.dishView.bigButton addTarget:self action:@selector(bigButtonClickEvent:) forControlEvents:UIControlEventTouchUpInside];
    
    NSString * pathURL = ALL_URL;
    NSURL * url = [NSURL URLWithString:[pathURL stringByAppendingFormat:@"%@",[[self.myProArr objectAtIndex:indexPath.row] valueForKey:@"ProductImg"]]];
    [cell1.leftImageView setImageWithURL:url placeholderImage:[UIImage imageNamed:ALL_NO_IMAGE]];
    return cell1;
}

看红色部分的代码,这点就是避免问题出现的办法,因为这个值是不同的cell值不同。

 

感觉自己的想法没有表达清楚,有什么问题直接留言。

 

posted on 2013-08-14 19:12  you Richer  阅读(234)  评论(0编辑  收藏  举报