Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone UIPageViewController在iOS 6中不返回任何手势识别器_Iphone_Objective C_Uikit_Uipageviewcontroller - Fatal编程技术网

Iphone UIPageViewController在iOS 6中不返回任何手势识别器

Iphone UIPageViewController在iOS 6中不返回任何手势识别器,iphone,objective-c,uikit,uipageviewcontroller,Iphone,Objective C,Uikit,Uipageviewcontroller,我正在尝试禁用UIPageViewController的平移手势识别器 在iOS 5上,我可以循环并禁用它们 for (UIGestureRecognizer* recognizer in self.pageViewController.gestureRecognizers) { if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) { recognizer.enabled = NO; } }

我正在尝试禁用UIPageViewController的平移手势识别器

在iOS 5上,我可以循环并禁用它们

for (UIGestureRecognizer* recognizer in self.pageViewController.gestureRecognizers) {
    if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
        recognizer.enabled = NO;
    }
}
在使用UIPageViewControllerTransitionStyleScroll的iOS 6上,页面视图控制器没有返回任何手势识别器

澄清 这可以归结为:

当UIPageViewController的转换样式设置为滚动,因此我无法访问手势识别器时,self.pageViewController.GestureRecograiners=0


我有什么办法可以绕开这件事吗?我不认为我做错了什么,因为curl转换工作正常。

您可以使用
uigestureerecognizer
的委托方法捕获并禁用任何手势。例如,您可以使用此委托回调:
gestureerecognizer:shouldReceiveTouch:
。只需确保为所有识别器设置委托即可。

此行为有一个有效的解决方案。所以,我打赌,在苹果修复之前,没有机会解决这个问题

我想到的一个解决方法是在
UIPageViewController
的顶部放置一个透明的子视图,并在其上添加一个
uipangestrerecognizer
,以截取这种手势,而不是向前移动。当需要禁用手势时,可以启用此视图/识别器

我用平移和轻拍手势识别器的组合进行了尝试,效果很好

这是我的测试代码:

- (void)viewDidLoad {
  [super viewDidLoad];

   UIPanGestureRecognizer* g1 = [[[UIPanGestureRecognizer alloc] initWithTarget:self
                                                                      action:@selector(g1Pan:)] autorelease];
  [self.view addGestureRecognizer:g1];

  UITapGestureRecognizer* s1 = [[[UITapGestureRecognizer alloc] initWithTarget:self
                                                                      action:@selector(g1Tap:)] autorelease];

  [self.view addGestureRecognizer:s1];

  UIView* anotherView = [[[UIView alloc]initWithFrame:self.view.bounds] autorelease];
  [self.view addSubview:anotherView];

  UIPanGestureRecognizer* g2 = [[[UIPanGestureRecognizer alloc] initWithTarget:self
                                                                      action:@selector(g2Pan:)] autorelease];
  [anotherView addGestureRecognizer:g2];

}
启用
g2
时,将阻止识别
g1
。另一方面,它不会阻止s1被识别


我理解这是一种黑客行为,但面对
UIPageViewController
中看似存在的错误(至少,实际行为与参考状态明显不同),我看不到任何更好的解决方案。

假设您可以找到手势识别器并将其删除,这是非常脆弱的。您正在使用苹果如何使用UIPageViewController在应用程序中提供功能的假定知识。如果这种情况发生变化(例如在iOS 5和iOS 6之间),则您的代码应用程序将开始以意外的方式运行。这几乎就像使用私有API—您无法保证它能在下一个操作系统版本中使用。

如果您使用KVC(键值编码)方法访问识别器,会发生什么?(我现在不在可以测试的地方。)

快速测试可能是检索手势识别器的数量:

[self.pageViewController countOfKey:@"gestureRecognizers"];
NSArray *recognizers = [self.pageViewController
                        mutableArrayValueForKey:@"gestureRecognizers"];
如果有效,您可以进一步检索识别器阵列:

[self.pageViewController countOfKey:@"gestureRecognizers"];
NSArray *recognizers = [self.pageViewController
                        mutableArrayValueForKey:@"gestureRecognizers"];
瘦,但也许

编辑:最终能够进行测试。使用了以下内容:

NSArray *pvcGRsNoKVC = [[NSArray alloc]
                       initWithArray:self.pageViewController.gestureRecognizers];
NSArray *viewGRsNoKVC = [[NSArray alloc] initWithArray:self.view.gestureRecognizers];

NSArray *pvcGRsKVC = [[NSArray alloc]
                     initWithArray:[self.pageViewController valueForKey:@"gestureRecognizers"]];
NSArray *viewGRsKVC = [[NSArray alloc]
                      initWithArray:[self.view valueForKey:@"gestureRecognizers"]];

这没什么区别。卷曲的风格在两方面都很好;滚动样式显示的数组不是nil,而是空的。不过,有趣的是,视图也没有放弃其识别器-尽管有滚动功能,因此它必须至少有一个平移识别器…

在UIPageViewController中找到了这一点。h:

//仅当转换样式为“UIPageViewControllerTransitionStylePageCurl”时才填充。 @属性(非原子、只读)NSArray*手势识别器


因此,这不是一个bug-根据设计,当设置滚动样式时,pageViewController不会获得手势识别器。

您始终可以尝试禁用页面视图控制器子视图上的用户交互:

for (UIScrollView *view in self.pageViewController.view.subviews) {
    if ([view isKindOfClass:[UIScrollView class]]) {
        view.scrollEnabled = NO;
    }
}

您可以从UIPageViewController通过UIScrollview访问UIPangestureRecognitor

for (UIView *view in self.pageController.view.subviews) {
    if ([view isKindOfClass:[UIScrollView class]])
    {
        UIScrollView *scrollView = (UIScrollView *)view;

        UIPanGestureRecognizer* panGestureRecognizer = scrollView.panGestureRecognizer;
        [panGestureRecognizer addTarget:self action:@selector(move:)];
    }
}

另一个解决方案,只是为了历史。 您可以使任何视图成为某个手势识别器断路器,它应该在该视图的矩形中工作。必须有另一个具有委托的UIPangestureRecognitor。它可以是具有一种方法的任何对象:

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;
}
您可以使用以下类来中断识别器:

@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
调用-lockForView后:页面控制器的手势无法在视图的框架中拖动。例如,我想锁定视图控制器的整个空间。所以从某个角度来看,我调用

[PageViewControllerLocker() lockForView:self.view];
另一方面

[PageViewControllerLocker() unlockForView:self.view];

根据UIPageViewController头文件,当数据源为nil时,将禁用手势驱动的导航

因此,当您想要禁用刷卡时,将datasource设置为nil,然后当您想要启用刷卡时,重置数据源

i、 e


如果UIPageViewControllers UIPangEstureRecognitor正在从其他PangEstureRecognitor(如滑动菜单)读取/吞咽所有事件

您可以轻松地扩展Bernies解决方案,并使UIScrollViews PangestureRecognitor要求另一个识别器失败。 大概是这样的:

for (UIView *view in pageViewController.view.subviews) {
    if ([view isKindOfClass:[UIScrollView class]]){
        UIScrollView *scrollView = (UIScrollView *)view;

        [scrollView.panGestureRecognizer requireGestureRecognizerToFail:otherRecognizer];
    }
}
这样滚动的PangestureRecognitor只会在我想要它的区域开火


这可能不是最好的未来证明解决方案,因为我们要求苹果不改变UIScrollView的UIPageViewController内部使用。但是…

在pageviewcontroller内部有一个名为quieingscrollview的子视图,它有3个手势识别器,用于控制PageView控制器 让他们使用

[[pageViewController.view.subviews objectAtIndex:0] gestureRecognizers]

在我的例子中,我的UIPageViewController上有一个UIView“信息面板”,但是页面视图控制器的手势识别器干扰了通过我的信息面板的导航

我的解决方案是将数据源设置为nil,但也不允许页面视图控制器在信息面板打开时更新焦点:

- (BOOL)shouldUpdateFocusInContext:(UIFocusUpdateContext *)context
{
    if (self.infoPanel) {
        return NO;
    } else {
        return YES;
    }
}

问题不是禁用手势识别器不起作用,而是我无法访问手势识别器,因为它们不是从带有滚动转换样式的UIPageViewController返回的。我发现了完全相同的问题。可能iOS6没有在UIPageVC上使用UIPangestureRecognitor。您是否尝试过插入自己的手势识别器,并以某种方式强制其超越默认的滑动/平移行为?如果您的转换样式设置为UIPageViewControllerTransitionStylePageCurl,则此功能在iOS 6上仍然有效->此处更简单->捕捉良好。显然我应该