简体   繁体   中英

why UICollectionView not calling didSelectItemAtIndexPath any more after scrolling the scrollView of it's cells?

I am using the UICollectionView to display some products. In the custom UICollectionViewCell , there is a custom UIScrollView , where there are some images which allow the users to do a quick preview.

To forward tap gesture from the UIScrollView to the UICollectionViewCell , i override the touches related methods as below:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (!self.dragging) {
        NSLog(@"Began ==>");
        [self.nextResponder touchesBegan:touches withEvent:event];
    }
    else {
        [super touchesBegan:touches withEvent:event];
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (!self.dragging) {
        NSLog(@"Moved ==>");
        [self.nextResponder touchesMoved:touches withEvent:event];
    }
    else {
        [super touchesMoved:touches withEvent:event];
    }

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (!self.dragging) {
        NSLog(@"Ended ==>");
        [self.nextResponder touchesEnded:touches withEvent:event];
    }
    else {
        [super touchesEnded:touches withEvent:event];
    }
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (!self.dragging) {
        NSLog(@"Cancelled ==>");
        [self.nextResponder touchesCancelled:touches withEvent:event];
    }
    else {
        [super touchesCancelled:touches withEvent:event];
    }
}

sometimes it doesn't work in some cases. For example, when the UICollectionView is loaded first time, didSelectItemAtIndexPath method can be called when you tap, but after some scrolls or taps, the method is not called anymore, even if you try to reload the UICollectionView , it's still not working.

I try to log the message in the touch methods of UICollectionViewCell , the touches & event is forwarded. But why the didSelectItemAtIndexPath of UICollectionView is called if the cell get the gesture?

Any advice would be much appreciated.

UPDATE: 1.the UICollectionViewCell is loaded from nib file.

It's not a good idea to use nextResponder if you're targeting a specific object. As you've just witnessed, the responder chain can change and you may not always get the object you expect. Why this is happening here can be any number of reasons, but you should use a more reliable means in this situation anyways.

Since UIScrollView is a subview of the UICollectionViewCell you can just pass the event directly to your superview [self.superview touchesMoved:touched withEvent:event]; You need to keep view hierarchy in mind when you're doing this and may have to call the superview's superview to reach the cell.

Also I wouldn't recommend using touches to intercept user interactions. I would highly recommend using UIGestureRecognizers as that will provide better more consistent functionality.

You should always call the super methods.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    NSLog(@"Began ==>");
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    NSLog(@"Moved ==>");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    NSLog(@"Ended ==>");
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesCancelled:touches withEvent:event];
    NSLog(@"Cancelled ==>");
}

Actually it's because of self.dragging understanding. The correct way to forward the tap gesture is as below:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.nextResponder touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.nextResponder touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (!self.dragging) {
        [self.nextResponder touchesEnded:touches withEvent:event];
    }
    else {
        [super touchesEnded:touches withEvent:event];
    }
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.nextResponder touchesCancelled:touches withEvent:event];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM