自定义UITableViewCell上的UIGestureRecognizer。在多个牢房上点火

时间:2015-07-19 03:15:46

标签: ios objective-c iphone uitableview uigesturerecognizer

我在这个奇怪的问题上高低搜索无济于事。我有一个自定义子类UITableViewCell。前后两个视图,当敲击时,单元翻转。这样做是这样的:

    - (IBAction)cellFrontTapped:(id)sender {
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    if (_cellFlag == 0)
    {
        _cellFlag = 1;
        [UIView transitionFromView:_cellFrontView toView:_cellBackView
                          duration:0.5
                           options:UIViewAnimationOptionTransitionFlipFromTop | UIViewAnimationOptionShowHideTransitionViews
                        completion:NULL];
        [self performSelector:@selector(cellBackTapped:) withObject:self afterDelay:15.0];
    }
}
- (IBAction)cellBackTapped:(id)sender {
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    if (_cellFlag == 1)
    {
        _cellFlag = 0;
        [UIView transitionFromView:_cellBackView toView:_cellFrontView
                          duration:0.5
                           options:UIViewAnimationOptionTransitionFlipFromBottom | UIViewAnimationOptionShowHideTransitionViews
                        completion:NULL];
    }
}

只需几个单元格即可正常工作。最多几页值得。但是当我加载一个更大的数据集时,点击一个单元格就会像预期的那样翻转它,但也会翻转其他单元格。 我意识到这是因为dequeueReusableCellWithIdentifier正在重复使用这些单元格,但我无法破译如何防止它。

我已尝试将其作为一个UIGestureRecognizer实施。我尝试过像这样使用didSelectRowAtIndexPath

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyTableViewCell *cell = (MyTableViewCell*)[tableView cellForRowAtIndexPath:indexPath];

    if (cell.cellFlag == 0)
    {
        [cell cellFrontTapped];
    }
    else
    {
        [cell cellBackTapped];
    }
}

这些都可以正常翻转单元格,但是tap事件总是翻转列表中的其他单元格。我发现的唯一解决方案是不要像dequeueReusableCellWithIdentifier这样使用:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell"];
    if (cell == nil) {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"MyTableViewCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];
    }

    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}

这是我当前的子类实现:

@implementation MyTableViewCell

- (void)awakeFromNib {
    // Adding the recognizer here produced the same result
    //UIGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cellTapped)];
    //tap.delegate = self;
    //[self addGestureRecognizer:tap];
    _cellFlag = 0;
}

- (void)cellFrontTapped {
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    _cellFlag = 1;
    [UIView transitionFromView:_cellFrontView toView:_cellBackView
                          duration:0.5
                           options:UIViewAnimationOptionTransitionFlipFromTop | UIViewAnimationOptionShowHideTransitionViews
                        completion:NULL];
    [self performSelector:@selector(cellBackTapped) withObject:self afterDelay:15.0];
}

- (void)cellBackTapped {
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    _cellFlag = 0;
    [UIView transitionFromView:_cellBackView toView:_cellFrontView
                          duration:0.5
                           options:UIViewAnimationOptionTransitionFlipFromBottom | UIViewAnimationOptionShowHideTransitionViews
                        completion:NULL];
}

-(void)cellTapped
{
    if (_cellFlag == 0)
    {
        [self cellFrontTapped];
    }
    else
    {
        [self cellBackTapped];
    }
}

@end

这是`configureCell:atIndexpath:

- (void)configureCell:(MyTableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath
{
    NSManagedObject *t = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    //here i set the labels and such
    cell.cellBackAmountLabel.text = [t.amount formattedAmount];
    //added 
    if ([self.flippedCellIndexes containsObject:indexPath])
    {
        [cell.contentView bringSubviewToFront:cell.cellBackView];
    }
    else
    {
        [cell.contentView bringSubviewToFront:cell.cellFrontView];
    }
}

我很茫然。在我的情况下,不使用dequeueReusableCellWithIdentifier会对性能产生重大影响。救命啊!

1 个答案:

答案 0 :(得分:2)

我建议将您的模型与您的视图分开。这意味着您应该跟踪哪些单元格应该呈现为翻转,而不是单元格本身。假设您在视图控制器中声明了NSArray(可能是NSMutableArray,甚至)flippedIndexes

如果您的数据集与您说的一样大,那么您可能应该使用稀疏数组而不是NSArray。使用NSMutableDictionary可以轻松实现稀疏数组。 NSMutableSet也可以发挥作用。

当出列单元格时,您可以检查应该翻转哪些单元格,可能是您的configureCell:atIndexPath:方法。基本上,如果indexPath显示在您的稀疏数组或设置上,则将单元格渲染为翻转。这意味着删除你在单元格中声明的cellFlag属性并根据我提到的模型切换其状态。要翻转单元格,请检查给定flippedIndexes的{​​{1}}属性并采取相应措施。像这样:

indexPath

这里我假设-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { MyTableViewCell *cell = (MyTableViewCell*)[tableView cellForRowAtIndexPath:indexPath]; if (![self.flippedIndexes containsObject:indexPath]) { [cell cellFrontTapped]; [self.flippedIndexes addObject:indexPath]; } else { [cell cellBackTapped]; [self.flippedIndexes removeObject:indexPath]; } } 属性使用NSMutableSet。请注意,只有在flippedIndexes中检查模型时才能正常工作,否则在滚动时你会神奇地清除单元格。

故事的道德是:不要将状态信息存储在排队的单元格中。