如何从表格单元格中删除 UIGestureRecognizer

发布于 2024-12-19 17:15:47 字数 2425 浏览 1 评论 0原文

我只想允许滑动删除 UITableView 的第一个单元格。 这一点很简单,但是我想在用户尝试滑动任何其他单元格时显示 UIAlert。我再次通过在除单元格 0 之外的每个单元格上使用 UIGestureRecognizer 来完成此工作。

我遇到的问题是一旦删除了顶行,我希望允许删除新的顶行。 就好像我需要删除分配给单元格的 UIGestureRecognizer ,但我不知道如何操作。

这是我的一些代码

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    BetCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BetCell"];

    Bet *bet = [self.bets objectAtIndex:([self.bets count]-indexPath.row-1)];
    cell.BFNeedLabel.text = bet.BFNeeded;

    if (indexPath.row != 0) {
    UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeDetected:)];
    swipeRecognizer.direction = (UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight);
    [cell addGestureRecognizer:swipeRecognizer];
    }

    return cell;

}

-(void)swipeDetected:(UIGestureRecognizer *)sender
{
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Info" message:@"You can only delete starting from the top cell" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
}

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
        return YES;
    } else  { 
        return NO;
    }
}

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // If the very first row
    if ((editingStyle == UITableViewCellEditingStyleDelete) && (indexPath.row == 0)) {
        Bet *betObj = [self.bets objectAtIndex:([self.bets count]-indexPath.row-1)];
        //Delete from array
        [self.bets removeObjectAtIndex:([self.bets count]-indexPath.row-1)];
        //Delete the row
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

        //Attempt to remove gesture recognizer from cell 0
        UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeDetected:)];
        swipeRecognizer.direction = (UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight);
        [[tableView cellForRowAtIndexPath:0]removeGestureRecognizer:swipeRecognizer];
    }
}

I want to only allow swipe to delete on the first cell of a UITableView.
This bit is easy, however I want to display a UIAlert when the user tries to swipe any other cell. Again I have this working by using UIGestureRecognizer on each cell apart from cell 0.

The problem i'm having is once the top row has been deleted, I want the new top row to be allowed to be deleted.
It's as if I need to remove the UIGestureRecognizer's i've assigned to the cell, but I can't figure out how to.

Here is some of my code

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    BetCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BetCell"];

    Bet *bet = [self.bets objectAtIndex:([self.bets count]-indexPath.row-1)];
    cell.BFNeedLabel.text = bet.BFNeeded;

    if (indexPath.row != 0) {
    UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeDetected:)];
    swipeRecognizer.direction = (UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight);
    [cell addGestureRecognizer:swipeRecognizer];
    }

    return cell;

}

-(void)swipeDetected:(UIGestureRecognizer *)sender
{
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Info" message:@"You can only delete starting from the top cell" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
}

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
        return YES;
    } else  { 
        return NO;
    }
}

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // If the very first row
    if ((editingStyle == UITableViewCellEditingStyleDelete) && (indexPath.row == 0)) {
        Bet *betObj = [self.bets objectAtIndex:([self.bets count]-indexPath.row-1)];
        //Delete from array
        [self.bets removeObjectAtIndex:([self.bets count]-indexPath.row-1)];
        //Delete the row
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

        //Attempt to remove gesture recognizer from cell 0
        UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeDetected:)];
        swipeRecognizer.direction = (UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight);
        [[tableView cellForRowAtIndexPath:0]removeGestureRecognizer:swipeRecognizer];
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

皓月长歌 2024-12-26 17:15:47

无需删除gestureRecognizer。在您的 swipeDetected 中找出您所在的单元格,并且仅在 indexPath.row != 0 时显示警报。

您的手势识别器将为您提供可以转换为表视图坐标空间的位置,该位置可用于获取该单元格的索引路径。

swipeDetected

CGPoint location = [sender locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
if ( indexPath.row != 0 {
// do alert
}

使用示例代码更新:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Test"];
    if ( !cell ) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"test"] autorelease];
        UISwipeGestureRecognizer *gr = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleCellSwipe:)];
        gr.direction = UISwipeGestureRecognizerDirectionRight + UISwipeGestureRecognizerDirectionLeft;
        gr.delegate = self;
        [cell addGestureRecognizer:gr];
        [gr release];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"Cell %d",indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ( indexPath.row == 0 )
        return UITableViewCellEditingStyleDelete;
    else 
        return UITableViewCellEditingStyleNone;
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return indexPath.row == 0;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // do stuff
}

- (void)handleCellSwipe:(UIGestureRecognizer *)gestureRecognizer
{
    if ( gestureRecognizer.state == UIGestureRecognizerStateRecognized ) {
        CGPoint location = [gestureRecognizer locationInView:self.tableView];
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
        if ( indexPath.row != 0 ) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Cell Swipe"
                                                            message:@"Cell in row not equal to 0 swiped"
                                                           delegate:nil 
                                                  cancelButtonTitle:nil
                                                  otherButtonTitles:@"OK", nil];
            [alert show];
            [alert release];
        }
    }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    CGPoint location = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
    return indexPath.row != 0;
}

No need to remove the gestureRecognizer. In your swipeDetected find out which cell you are, and only show the alert if indexPath.row != 0.

Your gesture recognizer will give you the location which can be translated to the table view coordinate space which turn can be used to get the indexPath for that cell.

In swipeDetected

CGPoint location = [sender locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
if ( indexPath.row != 0 {
// do alert
}

Update with sample code:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Test"];
    if ( !cell ) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"test"] autorelease];
        UISwipeGestureRecognizer *gr = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleCellSwipe:)];
        gr.direction = UISwipeGestureRecognizerDirectionRight + UISwipeGestureRecognizerDirectionLeft;
        gr.delegate = self;
        [cell addGestureRecognizer:gr];
        [gr release];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"Cell %d",indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ( indexPath.row == 0 )
        return UITableViewCellEditingStyleDelete;
    else 
        return UITableViewCellEditingStyleNone;
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return indexPath.row == 0;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // do stuff
}

- (void)handleCellSwipe:(UIGestureRecognizer *)gestureRecognizer
{
    if ( gestureRecognizer.state == UIGestureRecognizerStateRecognized ) {
        CGPoint location = [gestureRecognizer locationInView:self.tableView];
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
        if ( indexPath.row != 0 ) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Cell Swipe"
                                                            message:@"Cell in row not equal to 0 swiped"
                                                           delegate:nil 
                                                  cancelButtonTitle:nil
                                                  otherButtonTitles:@"OK", nil];
            [alert show];
            [alert release];
        }
    }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    CGPoint location = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
    return indexPath.row != 0;
}
够钟 2024-12-26 17:15:47

当您只需通过 caneditrowatindexpath 显示警报时,为什么要经历手势识别器的麻烦呢?我能看到的唯一问题是,如果您还使用编辑按钮 - 那么您会立即收到很多警报。

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
        return YES;
    } else  { 
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Info" message:@"You can only delete starting from the top cell" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }
}

如果您设置使用手势识别器,则只需在删除后在索引 0 上使用 reloadRowsAtIndexPaths:withRowAnimation: 这将重置第一个单元格。然而,您的 cellforrowatindexpath 在您的原始帖子中设置错误,并且无论哪种方式都会导致此设置发生奇怪的事情。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    BetCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BetCell"];

    if ( !cell ) //this is needed in case a cell was never created in the first place
        cell = [[[BetCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BetCell"] autorelease];

    Bet *bet = [self.bets objectAtIndex:([self.bets count]-indexPath.row-1)];
    cell.BFNeedLabel.text = bet.BFNeeded;

    if (indexPath.row != 0) {
        UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeDetected:)];
        swipeRecognizer.direction = (UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight);
        [cell addGestureRecognizer:swipeRecognizer];
    } else {//this is needed to reset a cell that is being reused (such as when you scroll off the page and return)
        for (UIGestureRecognizer *gesture in cell.gestureRecognizers) {
            [cell removeGestureRecognizer:gesture];
        }
    }

    return cell;

}

Why go through the trouble of a gesture recognizer when you can just show the alert through the caneditrowatindexpath. Only problem I can see is if you also use an edit button - then you'll get a lot of alerts at once.

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
        return YES;
    } else  { 
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Info" message:@"You can only delete starting from the top cell" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }
}

If your set on using the gesture recognizer you'll just have to use reloadRowsAtIndexPaths:withRowAnimation: on index 0 after the delete this will reset the first cell. However your cellforrowatindexpath is set up wrong in your original post and will cause weird things to happen for this setup either way.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    BetCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BetCell"];

    if ( !cell ) //this is needed in case a cell was never created in the first place
        cell = [[[BetCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BetCell"] autorelease];

    Bet *bet = [self.bets objectAtIndex:([self.bets count]-indexPath.row-1)];
    cell.BFNeedLabel.text = bet.BFNeeded;

    if (indexPath.row != 0) {
        UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeDetected:)];
        swipeRecognizer.direction = (UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight);
        [cell addGestureRecognizer:swipeRecognizer];
    } else {//this is needed to reset a cell that is being reused (such as when you scroll off the page and return)
        for (UIGestureRecognizer *gesture in cell.gestureRecognizers) {
            [cell removeGestureRecognizer:gesture];
        }
    }

    return cell;

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文