开发者

Gesture recognizer stopped working in iOS 4.3

开发者 https://www.devze.com 2023-02-16 10:19 出处:网络
My gesture recognition code worked fine in iOS 4.2 but in iOS 4.3 it does not work. I can\'t find any documented changes in gesture recognizers from iOS 4.2 to 4.3 but I have confirmed both on an iPad

My gesture recognition code worked fine in iOS 4.2 but in iOS 4.3 it does not work. I can't find any documented changes in gesture recognizers from iOS 4.2 to 4.3 but I have confirmed both on an iPad and in the simulator that my code is no longer working.

This is what I am doing:

In my view controller's ViewDidLoad method, I put:

UISwipeGestureRecognizer *swipeUpGesture = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedScreenLeft:)] autorelease];
swipeUpGesture.numberOfTouchesRequired = 2;
swipeUpGesture.direction = (UISwipeGestureRecognizerDirectionLeft);
[scrollView addG开发者_开发技巧estureRecognizer:swipeUpGesture];

In iOS 4.2 this works as expected but in iOS 4.3 swipedScreenLeft is never called even when I swipe with two fingers. Everything compiles and runs though with no errors or warnings.

Is there anything that might prevent this gesture recognizer from working in iOS 4.3 even though it works fine in iOS 4.2?

Also I have noticed that under iOS 4.2 if I touched the screen with two fingers but did not make the correct gesture, nothing would happen but in iOS 4.3 if I touch the screen with two fingers, it acts as if I am only touching with one finger. It is as if iOS 4.3 does not recognize multi touch events in my app.

Another note: my tapGestureRecognizer works fine in iOS 4.3 it's just the swipeGestureRecognizer that does not.


The problem is with UIScrollView only, I also made a rage about it: http://i.stack.imgur.com/dqx3d.png

[UPDATE 1] Here the solution:

The situation: A UIViewController's view has a UIScrollView as subview (the scroll view paging is disabled).

Code I use to attach the gesture the the UIView:

UISwipeGestureRecognizer *swipeLeftRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedScreenLeft:)];
[swipeLeftRecognizer setNumberOfTouchesRequired:2.0f];
swipeLeftRecognizer.delegate = self;
[swipeLeftRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];

[self.view addGestureRecognizer:swipeLeftRecognizer];

[swipeLeftRecognizer release];

To be iOS 4.3 enabled, I only had to add the UIViewController as a UIGestureRecognizerDelegate

Then, I used the following delegate method to intercept and allow the simultaneous recognition of the scrollView's panGesture with the view's swipe one. Here the code:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{

    if ([gestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
        return YES;
    }

    return NO;

}

[UPDATE 2]

To disable the UIScrollView panning with two fingers, I THINK that you have to make your scrollview, a custom subclass of the UISCrollView class and alter some behavior of the panGesture detector, BUT I didn't tried to do that. Instead I choosed a lazier solution, basically I enable/disable the scrollView scroll functionlity based on the current state of the UISwipeGestureRecognizer. Moreover, in order to prevent double touch movement in the other direction too, I attached another recognizer just for that purpose.

You have to create two properties for your swipe detectors.

@property (nonatomic,assign) UISwipeGestureRecognizer *swipeRightRecognizer;
@property (nonatomic,assign) UISwipeGestureRecognizer *swipeLeftRecognizer;

Then I coded like this:

[self setSwipeRightRecognizer:[[UISwipeGestureRecognizer alloc] initWithTarget:nil action:nil]];
[swipeRightRecognizer setNumberOfTouchesRequired:2.0f];
swipeRightRecognizer.delegate = self;
[swipeRightRecognizer setDirection:UISwipeGestureRecognizerDirectionRight];
[self addObserver:self forKeyPath:@"swipeRightRecognizer.state" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL];
[self.view addGestureRecognizer:swipeRightRecognizer];
[swipeRightRecognizer release];

[self setSwipeLeftRecognizer:[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedScreenLeft:)]];
[swipeLeftRecognizer setNumberOfTouchesRequired:2.0f];
swipeLeftRecognizer.delegate = self;
[swipeLeftRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[self addObserver:self forKeyPath:@"swipeLeftRecognizer.state" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL];
[self.view addGestureRecognizer:swipeLeftRecognizer];
[swipeLeftRecognizer release];

then add this method:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    if (self.swipeRightRecognizer.state == UIGestureRecognizerStateFailed) {
        self.scrollView.scrollEnabled = YES;
        return;
    }

    if ([self.swipeRightRecognizer numberOfTouches] != 2.0f) {
        self.scrollView.scrollEnabled = YES;   
    }
    else{
        self.scrollView.scrollEnabled = NO;   
    }
}

And update the existing method I posted in the previous "[UPDATE]":

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{

    if ([gestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
        if ([gestureRecognizer numberOfTouches] != 2.0f) {
            self.scrollView.scrollEnabled = YES;   
        }
        else{
            self.scrollView.scrollEnabled = NO;   
        }

        return YES;
    }
    return NO;
}

Finally, remove the observers in the dealloc:

[self removeObserver:self forKeyPath:@"swipeRightRecognizer.state"];
[self removeObserver:self forKeyPath:@"swipeLeftRecognizer.state"];

I bet there is a cleaner solution, but it works.. .

Hope it helps ;)


If you use UIImageView and you want to handle double taps on it, you should enable User Interaction. I wasted a lot of time to find out this.


Perhaps my code can help you with your problem. i've tested the code on an iPad with iOS 4.3 And it works perfectly

UISwipeGestureRecognizer *oSwipeLeft = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(mPreviousPage:) ] autorelease];
oSwipeLeft.numberOfTouchesRequired = 2;
oSwipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:oSwipeLeft];

UISwipeGestureRecognizer *oSwipeRight = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(mNextPage:) ] autorelease];
oSwipeRight.numberOfTouchesRequired = 2;
oSwipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:oSwipeRight];

UISwipeGestureRecognizer *oSwipeUp = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(mPreviousPage:) ] autorelease];
oSwipeUp.numberOfTouchesRequired = 2;
oSwipeUp.direction = UISwipeGestureRecognizerDirectionUp;
[self.view addGestureRecognizer:oSwipeUp];
0

精彩评论

暂无评论...
验证码 换一张
取 消