我已经为我的UITableViewCell创建了一个CheckBoxView控件。我面临的问题是,一旦我选中最上面一行之一并滚动相同的选中标记,就可以在最下面一行看到。这是因为可取消队列的行功能,我想知道如何解决它。这是实现。

CheckBoxView.m:

-(instancetype) initWithCoder:(NSCoder *)aDecoder {

    self = [super initWithCoder:aDecoder];
    [self setup];
    [self registerGesturesRecognizers];
    return self;
}

-(void) registerGesturesRecognizers {

    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(checkBoxTapped:)];

    [self addGestureRecognizer:tapGestureRecognizer];
}

-(void) checkBoxTapped:(UITapGestureRecognizer *) recognizer {

    if(self.checkBoxViewSelectionChanged) {
        if(!self.isChecked) {
            self.checkBoxViewSelectionChanged(self,self.isChecked);
            self.isChecked = YES;
        }
        else {
            self.checkBoxViewSelectionChanged(self,self.isChecked);

        }
    }
}

-(void) check {

    [_checkBoxImageView setImage:[UIImage imageNamed:@"small-check"]];

}

-(void) uncheck {

    _checkBoxImageView.image = nil;
}

-(void) setup {

    self.userInteractionEnabled = YES;
    self.layer.borderWidth = 0.5f;
    self.layer.borderColor = [UIColor lightGrayColor].CGColor;

    _checkBoxImageView = [[UIImageView alloc] initWithFrame:CGRectMake(1, 0, 23, 23)];
    [self addSubview:_checkBoxImageView];
}


这是cellForRowAtIndexPath方法:

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

    SamplesTableViewCell *cell = (SamplesTableViewCell *) [tableView dequeueReusableCellWithIdentifier:@"SamplesTableViewCell" forIndexPath:indexPath];

    Item *sample = [_samples objectAtIndex:[indexPath row]];

    cell.productNameLabel.text = sample.product.name;
    cell.productColorLabel.text = sample.productColor.name;
    [cell.productImageView setImage:sample.productColor.image];

    cell.checkboxView.checkBoxViewSelectionChanged = ^(CheckBoxView *checkBoxView, BOOL isChecked) {

        if(!isChecked) {
            [checkBoxView check];
            checkBoxView.isChecked = YES;
        }
        else {
            [checkBoxView uncheck];
            checkBoxView.isChecked = NO;
        }

    };

    return cell;
}


CheckBoxView实际上是Storyboard原型单元上的UIView,其类设置为CheckBoxView,因此不会在cellForRowAtIndexPath事件中动态创建它。当我运行上面的代码并选中最上面的行并滚动时,相同的选中标志出现在下面的行中。

更新:

这是我更新的代码,但仍会检查和取消选中底部的行。

  cell.checkboxView.checkBoxViewSelectionChanged = ^{

        if(!sample.isSelected) {

            [sample setSelected:YES];
            [cell.checkboxView check];
        }
        else
        {
            [sample setSelected:NO];
            [cell.checkboxView uncheck];
        }


    };

最佳答案

您的UIView不应保持复选框的isChecked状态。正如您所指出的,由于单元重用,因此将检查所有其他单元,因为正在使用相同的UIView

为数据提供支持的模型对象需要维护状态,或者是控制器。

例如:

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

   SamplesTableViewCell *cell = (SamplesTableViewCell *) [tableView dequeueReusableCellWithIdentifier:@"SamplesTableViewCell" forIndexPath:indexPath];

   // Some code...

   if ([self.myDatasource[indexPath.row] isChecked]) {
       cell.checkBoxView.isChecked = YES;
   }

   return cell;
}


只是一些粗糙的伪代码,但希望您能理解。维持此状态的可能方法是采用模型对象的形式,或者在您的UIViewController中有一个NSArray包含一个NSDictionary,表示UITableView中的每一行,其中每个键值对都维护一个特定的UITableViewCell的状态。

10-07 19:55