Another solution, just for history.
You can make any view to be some gesture recognizer breaker and it should work in that view's rectangle. There must be another UIPanGestureRecognizer with delegate. It can be any object with one method:
static UIPageViewController* getPageViewControllerFromView(UIView* v) {
UIResponder* r = v.nextResponder;
while (r) {
if ([r isKindOfClass:UIPageViewController.class])
return (UIPageViewController*)r;
r = r.nextResponder;
}
return nil;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if (getPageViewControllerFromView(otherGestureRecognizer.view))
{
otherGestureRecognizer.enabled = NO;
otherGestureRecognizer.enabled = YES;
}
return NO;
}
You can use following class for recognizer breaking purposes:
@interface GestureRecognizerBreaker : NSObject <UIGestureRecognizerDelegate>
{
UIGestureRecognizer* breaker_;
BOOL(^needsBreak_)(UIGestureRecognizer*);
}
- (id) initWithBreakerClass:(Class)recognizerClass
checker:(BOOL(^)(UIGestureRecognizer* recognizer))needsBreak;
- (void) lockForView:(UIView*)view;
- (void) unlockForView:(UIView*)view;
@end
@implementation GestureRecognizerBreaker
- (void) dummy:(id)r {}
- (id) initWithBreakerClass:(Class)recognizerClass checker:(BOOL(^)(UIGestureRecognizer*))needsBreak {
self = [super init];
if (!self)
return nil;
NSParameterAssert([recognizerClass isSubclassOfClass:UIGestureRecognizer.class] && needsBreak);
needsBreak_ = needsBreak;
breaker_ = [[recognizerClass alloc] initWithTarget:self action:@selector(dummy:)];
breaker_.delegate = self;
return self;
}
- (BOOL) gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer {
if (needsBreak_(otherGestureRecognizer)) {
otherGestureRecognizer.enabled = NO;
otherGestureRecognizer.enabled = YES;
}
return NO;
}
- (void) lockForView:(UIView*)view {
[view addGestureRecognizer:breaker_];
}
- (void) unlockForView:(UIView*)view {
[view removeGestureRecognizer:breaker_];
}
@end
This is works for example as singletone:
static GestureRecognizerBreaker* PageViewControllerLocker() {
static GestureRecognizerBreaker* i = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
i = [[GestureRecognizerBreaker alloc]
initWithBreakerClass:UIPanGestureRecognizer.class
checker:^BOOL(UIGestureRecognizer* recognizer) {
UIView* v = recognizer.view;
UIResponder* r = v.nextResponder;
while (r) {
if ([r isKindOfClass:UIPageViewController.class])
return YES;
r = r.nextResponder;
}
return NO;
}];
});
return i;
}
After calling -lockForView: page controller's gesture doesn't work on dragging in view's frame. For example I want to lock whole space of my view controller. So at some point in view controller method I call
[PageViewControllerLocker() lockForView:self.view];
And at another point
[PageViewControllerLocker() unlockForView:self.view];