UISwipeGestureRecognizer is called twice

I have problems with the view I am implementing.

This is the view that shows the pdf page in CATiledLayer. This tile view is inside the UISCrollView.

I had a view controlling myself as an example of "ZoomingPDFView". I made several modifications to recognize gestures when scrolling is not enabled, and tips on various topics and issues on this site. At that time, gestures were called once . But since I needed to separate the view and delegate scrolling in order to cache the pages and make a universal view, I created a view controller for gesture processing, and page loading methods improve the performance of the PDF view.

Now that I have a view on one side and a controller on the other, they double-check gestures, and I can’t even understand the problem.

this is console output

2010-11-19 11:45:08.370 ZoomingPDFViewerForIPad[20327:207] initWithFrame and page
2010-11-19 11:45:08.530 ZoomingPDFViewerForIPad[20327:207] drawPage
2010-11-19 11:45:08.531 ZoomingPDFViewerForIPad[20327:207] scale: 1.000000
2010-11-19 11:45:08.531 ZoomingPDFViewerForIPad[20327:207] pdf scale: 1.290062
2010-11-19 11:45:08.532 ZoomingPDFViewerForIPad[20327:207] pdf initial scale: 1.290062
2010-11-19 11:45:15.488 ZoomingPDFViewerForIPad[20327:207] left
2010-11-19 11:45:15.489 ZoomingPDFViewerForIPad[20327:207] left
2010-11-19 11:45:15.490 ZoomingPDFViewerForIPad[20327:207] initWithFrame and page
2010-11-19 11:45:15.538 ZoomingPDFViewerForIPad[20327:207] drawPage
2010-11-19 11:45:15.538 ZoomingPDFViewerForIPad[20327:207] scale: 1.000000
2010-11-19 11:45:15.539 ZoomingPDFViewerForIPad[20327:207] pdf scale: 1.290062
2010-11-19 11:45:15.539 ZoomingPDFViewerForIPad[20327:207] pdf initial scale: 1.290062
2010-11-19 11:45:15.540 ZoomingPDFViewerForIPad[20327:1a07] initWithFrame and page
2010-11-19 11:45:15.541 ZoomingPDFViewerForIPad[20327:5f07] initWithFrame and page
2010-11-19 11:45:15.593 ZoomingPDFViewerForIPad[20327:1a07] drawPage
2010-11-19 11:45:15.594 ZoomingPDFViewerForIPad[20327:1a07] scale: 1.000000
2010-11-19 11:45:15.594 ZoomingPDFViewerForIPad[20327:1a07] pdf scale: 1.290062
2010-11-19 11:45:15.595 ZoomingPDFViewerForIPad[20327:1a07] pdf initial scale: 1.290062
2010-11-19 11:45:15.695 ZoomingPDFViewerForIPad[20327:5f07] drawPage
2010-11-19 11:45:15.704 ZoomingPDFViewerForIPad[20327:5f07] scale: 1.000000
2010-11-19 11:45:15.707 ZoomingPDFViewerForIPad[20327:5f07] pdf scale: 1.290062
2010-11-19 11:45:15.713 ZoomingPDFViewerForIPad[20327:5f07] pdf initial scale: 1.290062

here is the code:

#import <UIKit/UIKit.h>

@class TiledPDFView;
@protocol PDFScrollViewDelegate;

@interface PDFScrollView : UIScrollView <UIScrollViewDelegate> {
 // The TiledPDFView that is currently front most
 TiledPDFView *pdfView;
 // The old TiledPDFView that we draw on top of when the zooming stops
 TiledPDFView *oldPDFView;


 // A low res image of the PDF page that is displayed until the TiledPDFView
 // renders its content.
 UIImageView *backgroundImageView;


 id<PDFScrollViewDelegate,NSObject> pdfViewDelegate;

 // current pdf zoom scale
 CGFloat pdfScale;

 CGPDFPageRef page;
 CGPDFDocumentRef pdf;
 CGFloat initialScale;
 TiledPDFView *initialTiledView;
 int currentPage;
 int pageCount;

 UITapGestureRecognizer *doubleTap,*twoFingerDoubleTap;
 UISwipeGestureRecognizer *rightSwipe, *leftSwipe;



}

@property (nonatomic,retain) id<PDFScrollViewDelegate> pdfViewDelegate;
-(id)initWithFrame:(CGRect)rect;
-(id)initWithFrame:(CGRect)frame andPDFPage:(CGPDFPageRef)aPage;
-(void)enableGestures;
-(void)drawPage;
@end

@implementation PDFScrollView
@synthesize pdfViewDelegate;

….

-(void)enableGestures{
 leftSwipe = [[UISwipeGestureRecognizer alloc ]initWithTarget:self action:@selector(handleRightSwipe:)];

 leftSwipe.direction = UISwipeGestureRecognizerDirectionRight;

 [self addGestureRecognizer:leftSwipe];

 //add right swipe
 rightSwipe = [[UISwipeGestureRecognizer alloc ]initWithTarget:self action:@selector(handleLeftSwipe:)];
 rightSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
 [self addGestureRecognizer:rightSwipe];



 doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTap:)];
 doubleTap.numberOfTapsRequired =2;
 doubleTap.numberOfTouchesRequired =1;
 [self addGestureRecognizer:doubleTap];


 twoFingerDoubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTwoFingerDoubleTap:)];
 twoFingerDoubleTap.numberOfTapsRequired =2;
 twoFingerDoubleTap.numberOfTouchesRequired =2;
 [self addGestureRecognizer:twoFingerDoubleTap];


}

// some more code
@end

#import <UIKit/UIKit.h>
#import "PDFScrollViewDelegate.h"
@class TiledPDFView;


@interface ZoomingPDFViewerForIPadViewController : UIViewController <UIScrollViewDelegate,PDFScrollViewDelegate>  {

 CGPDFPageRef page;



 CGPDFDocumentRef pdf;

 NSInteger currentPage;



 NSInteger pageCount;

 PDFScrollView *myScrollView;

 PDFScrollView *previousPage;
 PDFScrollView *nextPage;

}

-(id)initWithResourcePath:(NSString*)path ;
-(void)loadNextPage;
-(void)loadPreviousPage;
@end


@implementation ZoomingPDFViewerForIPadViewController

// some more code
#pragma mark -
#pragma mark PDFScrollViewDelegate methods
/* 
 called when user swipes right on the view
 */

-(void)viewDetectedRightSwipe:(PDFScrollView*)pdfScrollView withGesture:(UISwipeGestureRecognizer*)recognizer {
  NSLog(@"right");
 if (currentPage>1){
  //decreate page counter
  currentPage--;


  // release old next page

  if(nextPage){
   [nextPage release];
  }
  // set the actual page as the next one
  nextPage = [myScrollView retain];

  // remove the view from the actual view
  [myScrollView removeFromSuperview];

  // check if the previous page is loaded
  if(!previousPage)
   [self loadPreviousPage];

  // set the previouse page as the actual page
  myScrollView = previousPage;

  myScrollView.pdfViewDelegate = self;
  //[myScrollView drawPage];
  // load a new previous page
  //[NSThread detachNewThreadSelector:@selector(loadNextPage) toTarget:self withObject:nil];
  //[self loadNextPage];


 }
}
/*
 called when user swipes left on the view
 */
-(void)viewDetectedLeftSwipe:(PDFScrollView*)pdfScrollView withGesture:(UISwipeGestureRecognizer*)recognizer{
 NSLog(@"left");
 // if the end of the document isn't reached 
 if (currentPage<pageCount){
  //increment current page
  currentPage++;
  // if a previous page has been loaded release it
  if (previousPage) {
   [previousPage release];
  }
  // assing the actual view to as a previous page  and retain it before it gets release by superview
  previousPage = [myScrollView retain];
  // remove the view from the super view 
  [myScrollView removeFromSuperview];

  // if a next page hasn't beeen loaded yet, load it on this thread
  if (!nextPage)
   [self loadNextPage];

  // assign the next page as the current page
  myScrollView = nextPage;

  // put the current page the delegate
  myScrollView.pdfViewDelegate = self;

  // add the current page to the super view
  [[self view] addSubview:myScrollView];

  // load a next page.
  [NSThread detachNewThreadSelector:@selector(loadNextPage) toTarget:self withObject:nil];
 //[self loadNextPage];


 }  

}

/*
 called when the user taps the screen
 */
-(void)viewDetectedTapping:(PDFScrollView*)pdfScrollView withGesture:(UITapGestureRecognizer*)recognizer {
 NSLog(@"tapped");
 [myScrollView setZoomScale:1.0f animated:YES];


}


-(void)loadNextPage {
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 CGPDFPageRef aPage =  CGPDFDocumentGetPage(pdf, currentPage+1);
 nextPage = [[PDFScrollView alloc] initWithFrame:myScrollView.frame andPDFPage:aPage ];
 [pool release];
}



-(void)loadPreviousPage {

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
 CGPDFPageRef aPage =  CGPDFDocumentGetPage(pdf, currentPage-1);
 previousPage = [[PDFScrollView alloc] initWithFrame:myScrollView.frame andPDFPage:aPage];
 [pool release];
}
@end

this is the code that triggers the gesture.

-(void)handleRightSwipe:(UIGestureRecognizer*)gesture {


    if ([pdfViewDelegate respondsToSelector:@selector(viewDetectedRightSwipe:withGesture:)]) {
        UISwipeGestureRecognizer *swipe = (UISwipeGestureRecognizer*)gesture;
        [pdfViewDelegate viewDetectedRightSwipe:self withGesture:swipe];

    }




}
-(void)handleLeftSwipe :(UIGestureRecognizer*)gesture{


    if ([pdfViewDelegate respondsToSelector:@selector(viewDetectedLeftSwipe:withGesture:)]) {
        UISwipeGestureRecognizer *swipe= (UISwipeGestureRecognizer*)gesture;
        [pdfViewDelegate viewDetectedLeftSwipe:self withGesture:swipe];

    }

}

Thank you in advance for your time.

+3
source share
8 answers

There is an error in iOS 4.xx that causes the callback to be called twice if you delete FromSuperview inside the callback.

You can set the included NO property to removeFromSuperview:

- (void)removeFromSuperview
{
    for(UIGestureRecognizer* gestureRecognizer in self.gestureRecognizers) {
        gestureRecognizer.enabled = NO;
    }
    [super removeFromSuperview];
}

- (void)willMoveToSuperview:(UIView *)newSuperview
{
    for(UIGestureRecognizer* gestureRecognizer in self.gestureRecognizers) {
        gestureRecognizer.enabled = YES;
    }
    [super willMoveToSuperview:newSuperview];
}

However, the callback still works, even if it is disabled. Therefore, you should check the included property in the callback:

- (void)didSwipeRight:(UISwipeGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.enabled) {
            //do something useful...
    }
}
+1
source

, , , :

[myScrollView removeFromSuperview];

- UISwipeGestureRecognizer . UIGestureRecognizer .

, removeFromSuperview:

for (UIGestureRecognizer *g in myScrollView.gestureRecognizers) {
    g.enabled = NO;
    g.delegate = nil;
}
[myScrollView removeFromSuperview];

, .

+7

@Pacu,

!

. UIGestureRecognizer , . - . ... , , , . , , .

, , , , , , .

switch (sender.state) {
    case UIGestureRecognizerStateBegan:
        self.dragging = [self objectToRotateOrPinch:sender];
        break;
    case UIGestureRecognizerStateEnded:
        self.dragging = nil;
        break;
    case UIGestureRecognizerStateCancelled:
        self.dragging = nil;
        break;
    case UIGestureRecognizerStateFailed:
        self.dragging = nil;
        break;
    case UIGestureRecognizerStateChanged:
        // rotate or pinch
        break;
    default:
        break;
}

, , , , == UIGestureRecognizerStateEnded.

+5

:

-(void)handleRightSwipe:(UIGestureRecognizer*)gesture {
    if (gesture.state != UIGestureRecognizerStateEnded)
        return; //gesture not finished yet

    if ([pdfViewDelegate respondsToSelector:@selector(viewDetectedRightSwipe:withGesture:)]) {
        UISwipeGestureRecognizer *swipe = (UISwipeGestureRecognizer*)gesture;
        [pdfViewDelegate viewDetectedRightSwipe:self withGesture:swipe];
    }
}

, .

+1

- , , , .

- (void) leftSwipe: (UISwipeGestureRecognizer *) recognizer;
{
    if (![recognizer isEnabled]) return;    
    [recognizer setEnabled:NO];
    [recognizer performSelector:@selector(setEnabled:) withObject: [NSNumber numberWithBool:YES] afterDelay:0.1];
       // your gesture handling code here....

, , , , . - , .

+1

, , , (Gesture Fires), removeFromSuperview... sniplet ...

- (void)removeFromSuperview
{
    for(UIGestureRecognizer* gesture in [self gestureRecognizers])
        [self removeGestureRecognizer:gesture];
    [super removeFromSuperview];
}
+1

, removeGestureRecognizer: UIView.

-(void)handleLeftSwipe:(UIGestureRecognizer *)gesture
{
    UIView *vw = [gesture view];
    [view removeGestureRecognizer:gesture];
    [view removeFromSuperview];
}

, , "", .

,

+1

aBitOvvious , "" , , . , , . , , , .

-1

Source: https://habr.com/ru/post/1775857/


All Articles