如果同时触发滑动手势和后退按钮,导航栏会变得很时髦

Posted

技术标签:

【中文标题】如果同时触发滑动手势和后退按钮,导航栏会变得很时髦【英文标题】:Navigation Bar gets funky if Swipe Gesture and Back Button are triggered at the same time 【发布时间】:2015-01-09 00:42:23 【问题描述】:

今天我们的一位测试人员向我展示了,如果他在向后滑动的同时按下导航栏的后退按钮,会产生一个非常有趣的导航栏行为:

如果我们在第三个视图控制器上执行此操作而不是返回顶部,然后再次进入一层并单击后退按钮,大多数情况下导航栏不会消失,或者可能不会动画。或者不出现在更深层次。或者虽然不在顶视图控制器中,但停用后退按钮。

有时此消息会打印到控制台:

在意外状态下完成导航转换。导航栏子视图树可能已损坏。

事实证明它必须在 Apples 类中,因为我能够用普通类重现它。代码在GitHub。您必须在手机上运行该应用程序才能同时执行手势和按钮点击。

我还准备了video。

我该如何解决?

【问题讨论】:

为什么投反对票?这是一个很好的问题,我自己也有同样的问题。我的答案如下。 @MikeTaverne,我怀疑否决票与问题有关。有些人不喜欢“危险风格”的问答,即使在常见问题解答和用户界面中鼓励这样做。其他反对票是报复票。 【参考方案1】:

为了解决这个问题,我禁用了导航栏的用户交互。为此,我将 UINavigationViewController 子类化并使用 Key-Value-Observing 来检测手势识别器的状态。

#import "NavigationViewController.h"


@interface NavigationViewController ()
@end

@implementation NavigationViewController

- (void)viewDidLoad

    [super viewDidLoad];
    [self.interactivePopGestureRecognizer addObserver:self
                                           forKeyPath:@"state"
                                              options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
                                              context:NULL];





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

    if ([keyPath isEqual:@"state"]) 
        [self recognizer:object
            changedState:[change[@"new"] integerValue]
                oldState:[change[@"old"] integerValue]];

     else 
        [super observeValueForKeyPath:keyPath
                             ofObject:object
                               change:change
                              context:context];
    


- (void)recognizer:(UIGestureRecognizer *)recognizer
      changedState:(UIGestureRecognizerState)newState
          oldState:(UIGestureRecognizerState)oldState

    switch (newState) 
        case UIGestureRecognizerStateEnded:
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateFailed:
            [self.navigationBar setUserInteractionEnabled:YES]; break;

        case UIGestureRecognizerStateBegan:
            [self.navigationBar setUserInteractionEnabled:NO]; break;

        default:
            break;
    



- (void)dealloc

    [self.interactivePopGestureRecognizer removeObserver:self forKeyPath:@"state"];


@end

您也可以在GitHub 上找到固定代码。

【讨论】:

【参考方案2】:

假设您有一个带有视图控制器 A --> B --> C 的导航控制器。

当您在 C 上,滑回 B,然后在抬起滑动手指之前触摸 B 上的返回按钮时,会出现问题。

为了防止这种情况:

在 B 视图中DidDisappear:

    navigationItem.hidesBackButton = true

在 B viewDidAppear 中:

    navigationItem.hidesBackButton = false

这具有防止触摸 B 的后退按钮直到滑动完成的效果。

【讨论】:

不管怎样,Apple 自己的应用程序无法处理这种情况。例如,可以在邮件和设置应用程序中轻松重现该错误。

以上是关于如果同时触发滑动手势和后退按钮,导航栏会变得很时髦的主要内容,如果未能解决你的问题,请参考以下文章

带有自定义后退按钮的滑动手势冻结根视图控制器

使用左栏按钮在导航栏上滑动返回手势

移动浏览器:后退按钮上的更新元素

SwiftUI - navigationBarBackButtonHidden - 向后滑动手势?

Hammer.js 在 Angular 中向左滑动手势动画

ios15在隐藏导航栏时向后半滑动会留下顶部空白空间 - SwiftUI