【问题标题】:iOS: popViewController unexpected behavioriOS:popViewController 意外行为
【发布时间】:2011-07-15 03:12:59
【问题描述】:

我一直在互联网上寻找解决方案。我找不到任何东西。 所以: 我正在使用 UINavigationController。我将两个 UIViewControllers 推到它上面。在第二个推送的 ViewController 中,我正在执行此代码:

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
NSLog([error localizedDescription]);
[self.navigationController popViewControllerAnimated:YES]; }

预期发生的事情是最后推送的 ViewController 消失了。在这个应用程序中,我在少数地方执行此操作,并且在这个 ViewController 中可以正常工作。 发生的情况是只有后退按钮离开屏幕(动画),但其他一切都留在屏幕上。在控制台输出中,执行此行时会打印出两件事:

2011-03-14 16:32:44.580 TheAppXY[18518:207] 嵌套弹出 动画可能导致损坏 导航栏

2011-03-14 16:32:53.507 TheAppXY[18518:207] 完成一个 意外的导航过渡 状态。导航栏子视图树 可能会损坏。

我找不到任何信息的两条错误消息。 我正在使用 XCode 4 和 iOS SDK 4.3。也许任何人都可以帮助我解决这个问题。

【问题讨论】:

  • 我想是我自己想出来的。我认为这是因为我尝试过早地弹出视图控制器。如果反向地理编码器传递了一个地址(在 ViewDidLoad 中启动)并且失败,则视图还没有出现,因此动画弹出显然不能很好地工作。我现在在 ViewDidAppear 中实现了反向地理编码器的启动,一切似乎都运行良好。新手或多或少的错误。但我想知道没有关于它的信息
  • 最近,我遇到了同样的问题。原因是:-我试图错误地弹出视图控制器两次。您可以通过在推送和弹出视图控制器上设置断点来检查此崩溃

标签: xcode ios uinavigationcontroller


【解决方案1】:

我在我的代码中遇到了类似的情况,消息说:

嵌套推送动画会导致导航栏损坏

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

我对这个问题的发现是我正在快速连续地一个接一个地推动 2 个视图控制器,并且两个都是动画的。

在您的情况下,您可能会一个接一个地弹出多个带有动画的视图控制器。

因此,当一个视图正在播放动画时,您不应该在另一个视图上开始动画。

我还发现,如果我在一个视图上禁用动画,错误消息就会消失。

就我而言,这是流程逻辑的问题,因为我不打算一个接一个地推送 2 个视图控制器。一个在 switch case 逻辑中被推送,另一个在结束后被推送。

希望这对某人有所帮助。

【讨论】:

  • 对我来说,这里的关键是:“......而且两者都是动画的。”谢谢!
  • 您对处理您想要这样做的情况有什么建议吗?例如,当我将视图控制器推送到堆栈上时,我经常看到这种情况,然后显示 UIAlertView。我仍然想展示它们,我只希望视图被推送到堆栈上,然后显示警报视图,而不必实现一堆委托方法。
  • 感谢我将这个Animated:YES 更改为Animated:NO 并在viewDidAppear 上调用我的pop 方法解决了问题
  • 不是一个优雅的解决方案,但我通过在第二个动作上延迟 0.5 秒来消除此错误,因为将动画 no 设置为第一个 popviewcontroller 对我不起作用。
【解决方案2】:

您可以在任何时候尝试在viewDidAppear 之前弹出此消息。如果你设置了一个标志,那么只需检查viewDidAppear中的那个标志,你不会有问题。

【讨论】:

  • 这似乎是最安全的方法
【解决方案3】:

我为 UINavigationController 创建了一个插入式替代品,它将为您排列动画并完全避免这个问题。

BufferedNavigationController获取它

【讨论】:

  • 嗨,andrew,你还支持上面的类吗?出于某种原因,它对我不起作用,您可以在此处看到:stackoverflow.com/questions/16634337/…
  • 另请参阅下面我的 UINavigationControllerWithQueue 答案
【解决方案4】:

我也遇到了这个问题,这是造成我的问题的原因:

  1. 在 RootViewController 中,我使用了几个 UISegmentedControl 对象来确定接下来要加载哪些视图。
  2. 在那个(子/第二个)视图中,我弹出(通过使用“返回”按钮)回到 RootViewController。
  3. 在 RootViewController 中,我正在处理 viewWillAppear 以将我的每个 UISegmentedControl 对象“重置”为 -1 的 selectedSegmentIndex(这意味着没有任何段看起来“被按下”)。
  4. “重置”触发了我的每个 UISegmentedControl 对象,以触发它们关联的(和单独的)IBAction。
  5. 由于我没有处理 -1 的“选择”,我有多个方法同时触发,都试图推送不同的视图。

我的解决方法?当 selectedSegmentIndex == -1 时,我收紧了我的 if...then 语句并放弃执行 UISegmentedControl IBActions 中的任何代码。

我仍然不确定为什么会出现“pop”动画错误而不是“push”错误,但至少找出了我的错误并修复了它!

希望这对其他人有帮助!

【讨论】:

    【解决方案5】:

    是的,不幸的是苹果没有同步 UINavigationController 的动画。 Andrew 的解决方案非常好,但是如果你不想覆盖它的全部功能,还有一个更简单的解决方案,覆盖这两个方法:

    // navigation end event
    
    - ( void )  navigationController    : ( UINavigationController* ) pNavigationController 
                didShowViewController   : ( UIViewController*       ) pController 
                animated                : ( BOOL                    ) pAnimated
    {
    
        if ( [ waitingList count ] > 0 ) [ waitingList removeObjectAtIndex : 0 ];
        if ( [ waitingList count ] > 0 ) [ super pushViewController : [ waitingList objectAtIndex : 0 ] animated : YES ];
    
    }
    
    
    - ( void )  pushViewController  : ( UIViewController* ) pController 
                animated            : ( BOOL ) pAnimated
    {
    
        [ waitingList addObject : pController ];
        if ( [ waitingList count ] == 1 ) [ super pushViewController : [ waitingList objectAtIndex : 0 ] animated : YES ];
    
    }
    

    并创建一个名为 waitingList 的 NSMutableArray 实例变量,就完成了。

    【讨论】:

    • 我采用了这个想法并将其推广到也可以在下面的答案 UINavigationControllerWithQueue 中与 popViewController* 一起使用
    【解决方案6】:

    当我使用故事板时,我会遇到这个问题。我犯了一个错误: 我有一个带有执行SegueWithIdentifier 操作的 UIButton。所以我将带有 Button 的 push segue 与另一个 ViewController 链接起来,所以会出现这个问题。

    解决: 链接 UIButton 中的按钮动作,并链接两个 ViewController 之间的 push segue。

    【讨论】:

      【解决方案7】:

      结合 MilGra 和 Andrew 的答案,我得到了一些可靠的东西,并且是一个更简单的 UINavigationController 替代品。

      这改进了 MilGra 的答案,使其适用于推送和弹出,但比 Andrew 的 BufferedNavigationController 更简单。 (使用 BufferedNavigationController 我偶尔会遇到永远无法完成的过渡,只会显示黑屏。)

      这整件事在 iOS8 上似乎没有必要,但在 iOS7 上我仍然需要。

      @implementation UINavigationControllerWithQueue {
          NSMutableArray *waitingList;
      }
      
      -(void) viewDidLoad {
          [super viewDidLoad];
          self.delegate = self; // NOTE: delegate must be self!
          waitingList = [[NSMutableArray alloc] init];
      }
      
      # pragma mark - Overrides
      
      -(void) pushViewController: (UIViewController*) controller
                        animated: (BOOL) animated {
          [self queueTransition:^{ [super pushViewController:controller animated:animated]; }];
      }
      
      - (UIViewController *)popViewControllerAnimated:(BOOL)animated {
          UIViewController *result = [self.viewControllers lastObject];
          [self queueTransition:^{ [super popViewControllerAnimated:animated]; }];
          return result;
      }
      
      - (NSArray*)popToRootViewControllerAnimated:(BOOL)animated {
          NSArray* results = [self.viewControllers copy];
          [self queueTransition:^{ [super popToRootViewControllerAnimated:animated]; }];
          return results;
      }
      
      # pragma mark - UINavigationControllerDelegate
      
      -(void) navigationController: (UINavigationController*) navigationController
             didShowViewController: (UIViewController*) controller
                          animated: (BOOL) animated {
          [self dequeTransition];
      }
      
      # pragma mark - Private Methods
      
      -(void) queueTransition:(void (^)()) transition {
          [waitingList addObject:transition];
          if (waitingList.count == 1) {
              transition();
          }
      }
      
      -(void) dequeTransition {
          if (waitingList.count > 0) {
              [waitingList removeObjectAtIndex:0];
          }
          if (waitingList.count > 0) {
              void (^transition)(void) = [waitingList objectAtIndex:0];
              if (transition) {
                  transition();
              }
          }
      }
      
      @end
      

      【讨论】:

      • 在模拟器中运行良好,但在设备上并不可靠——所以最后,不推荐使用这种方法。
      猜你喜欢
      • 2017-03-10
      • 2019-05-01
      • 2011-04-27
      • 2019-12-07
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多