【问题标题】:Pop to root view when tab is selected选择选项卡时弹出到根视图
【发布时间】:2011-11-30 19:56:18
【问题描述】:

我在一些我认为可能很容易的事情上遇到了一些麻烦。 I have a table in my root view controller, when a row is selected I push a new view and from there I go to another tab.

我的问题是如何确保一旦用户点击第一个选项卡,导航控制器就会弹出到根目录?

【问题讨论】:

    标签: iphone ios uinavigationcontroller uitabbarcontroller


    【解决方案1】:

    在选项卡栏上选择每个选项卡时调用以下委托。

    -(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
    

    将以下代码放入此委托方法中。

    if ([viewController isKindOfClass:[UINavigationController class]]) 
        {
            [(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
        }
    

    它在我的应用上运行良好。

    【讨论】:

    • 对我真的很有帮助,根据我的要求在我的应用程序中工作正常。
    • 代理是什么文件?我尝试创建一个 UINavigationController 并将其指定为委托。我看到它在 viewDidLoad 上被调用,但将其指定为 UITabBarDelegate 或 UITabBarControllerDelegate 的委托不会调用此方法。
    • 我有点困惑。你能告诉我我在哪里添加这段代码
    • 做不到这个不行的可以试试在头文件(.h)中添加UITabBarControllerDelegate,在实现文件(.m)中添加self.tabBarController.delegate = self;。跨度>
    【解决方案2】:

    对于 Swift 爱好者:

    import UIKit
    
    class YourTabBarControllerHere: UITabBarController,
    UITabBarControllerDelegate {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.delegate = self;
        }
    
        func tabBarController(tabBarController: UITabBarController,
            didSelectViewController viewController: UIViewController) {
                if let vc = viewController as? UINavigationController {
                    vc.popViewControllerAnimated(animated: false);
                }
        }
    }
    

    编辑: Swift 3 更新,感谢 @Justin Oroz 指出这一点。

    【讨论】:

    • 作为 OP 对 ROOT 控制器的问题,它应该是(在 Swift 3 语法中)vc.popToRootViewController(animated: false)
    【解决方案3】:

    在 Swift 3.1 中

    将 UITabBarControllerDelegate 添加到您的 TabBar 类:

    类YourClass:UITabBarController,UITabBarControllerDelegate {

    之后:

    覆盖 func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {

    let yourView = self.viewControllers![self.selectedIndex] as! UINavigationController
    yourView .popToRootViewControllerAnimated(false) 
    

    }

    【讨论】:

      【解决方案4】:

      您正在尝试做的事情听起来有点奇怪。您是否阅读过关于结合 UINavigationControllers 和 UITabBarControllers 的人机界面指南?

      但是,您需要做的是通过为您的 UITabBarController 设置委托并实现 tabBarController:didSelectViewController: 委托方法来检测选项卡的选择。在这种方法中,您需要使用 UINavigationController 的 popToRootViewControllerAnimated: 方法弹回根视图控制器。

      【讨论】:

      • 如果您查看 Apple 的 Phone.app,收藏夹和最近选项卡的行为与 OP 想要的相同。
      • 当您选择表格行时,电话应用程序不会切换选项卡 - 这是我正在查询的行为,当用户点击不同的选项卡时不会弹出到根目录。
      • 啊,是的,OP 的问题并不完全是 OP 的意思,即“从那里我转到另一个选项卡”。用户是否选择另一个选项卡或应用程序是否自动切换。
      【解决方案5】:
      [self.navigationController popToRootViewControllerAnimated:NO];
      

      【讨论】:

      • 将动画更改为 NO 实际上对我有帮助。当我将动画设置为 YES 时,我的标签栏或导航控制器中的任何其他按钮都不起作用。
      【解决方案6】:

      斯威夫特 4.2

      对我有用的解决方案是继承 UITabBarController 并添加两个委托函数,如下所示:

      import UIKit
      
      class MyCustomTabBarController: UITabBarController, UITabBarControllerDelegate {
          var previousSelectedTabIndex:Int = 0
      
      override func viewDidLoad() {
          super.viewDidLoad()
          self.delegate = self
      }
      
      func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
          self.previousSelectedTabIndex = tabBarController.selectedIndex
      }
      
      
      override func tabBar(_ tabBar: UITabBar, didSelect item:
          UITabBarItem) {
          let vc = self.viewControllers![previousSelectedTabIndex] as! UINavigationController
          vc.popToRootViewController(animated: false)
      
      }
      
      }
      

      确保你将动画设置为 false 否则你会得到

       Unbalanced calls to begin/end appearance transitions for the targeted ViewController
      

      【讨论】:

        【解决方案7】:

        试试这个。

        class TabBarClass: UITabBarController {
        
            override func viewDidLoad() {
                super.viewDidLoad()
            }
        
            override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
                let vc = self.viewControllers![selectedIndex] as! UINavigationController
                vc.popToRootViewController(animated: false)
            }
        }
        

        【讨论】:

          【解决方案8】:

          Swift 5.1 答案:

            class YourTabBarName: UITabBarController, UITabBarControllerDelegate
              {
          
               override func viewDidLoad()
                  {
                      super.viewDidLoad()
                      self.delegate = self
                  }
          
          
               func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController)
                  {
                      if let vc = viewController as? UINavigationController
                      { vc.popToRootViewController(animated: false) }
                  }
              }
          

          【讨论】:

            【解决方案9】:

            首先,您应该创建 UITabbarController 的子类并添加 Observer:

            - (void)viewDidLoad {
                [super viewDidLoad];
                [self.tabBar addObserver:self forKeyPath:@"selectedItem" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
            }
            

            当tabbar被选中时,我们会在方法中处理:

            -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
                if ([keyPath isEqualToString:@"selectedItem"] && [object isKindOfClass:[UITabBar class]]){
                    UITabBar *bar = (UITabBar *)object; // The object will be the bar we're observing.
                    // The change dictionary will contain the previous tabBarItem for the "old" key.
                    UITabBarItem *wasItem = [change objectForKey:NSKeyValueChangeOldKey];
                    NSUInteger was = [bar.items indexOfObject:wasItem];
                    // The same is true for the new tabBarItem but it will be under the "new" key.
                    UITabBarItem *isItem = [change objectForKey:NSKeyValueChangeNewKey];
                    NSUInteger is = [bar.items indexOfObject:isItem];
                    if (is == was) {
                       UIViewController *vc = self.viewControllers[is];
                        if ([vc isKindOfClass:[UINavigationController class]]) {
                            [(UINavigationController *)vc popToRootViewControllerAnimated:YES];
                        }
                    }
                }
            }
            

            【讨论】:

              【解决方案10】:

              UTabController 建议使用不同的用户体验让用户“弹出到根目录”。切换回选项卡时,它会保留之前的完整 UINav 堆栈。如果他们再次点击栏项目(点击选定的选项卡),那么它才会弹出到根目录。这都是自动的。某些应用程序(例如 instagram)允许第三次点击滚动到顶部。

              我建议坚持使用默认值,因为这是用户所期望的。

              【讨论】:

                【解决方案11】:

                以下内容对我有用。swift 3中的这段代码:

                1> 继承 UITabbarController 并用一个 iVAr 实现以下两个方法:
                class MyTabBarController: UITabBarController ,UITabBarControllerDelegate { var previousSelectedTabIndex : Int = -1 }

                2>在viewdidLoad中设置tabbar代理

                override func viewDidLoad() {    
                    super.viewDidLoad()
                    self.delegate = self    // you must do it}  
                
                func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
                
                    self.previousSelectedTabIndex = tabBarController.selectedIndex
                }     
                func tabBarController(_ tabBarController: UITabBarController,
                                               shouldSelect viewController: UIViewController) -> Bool {    
                
                    if  self.previousSelectedTabIndex == tabBarController.selectedIndex {
                        let   nav  =  viewController as! UINavigationController // mine in nav_VC
                        for vc in nav.childViewControllers {
                            if vc is YUOR_DESIRED_VIEW_CONTROLLER {
                            nav.popToViewController(vc, animated: true)
                            return false// IT WONT LET YOU GO TO delegate METHOD
                            }
                        }
                    }
                 return true
                }    
                

                tabBarController.selectedIndex 给你选择的标签

                在 tabBarController_shouldSelect_viewController 方法中,您可以通过一些简单的计算来设置所需的视图控制器。
                如果您没有使用上述两种方法获得上述代码,并且您会了解两者如何协同工作

                【讨论】:

                • 这种方法记录目标 ViewController 的开始/结束外观转换的不平衡调用,即使它确实有效。我正在尝试找到一个不会记录错误的解决方案。
                【解决方案12】:

                使用选中的视图控制器来弹出ToRootViewController。基本上你需要转换这个实例。

                斯威夫特

                ((selectedViewController) as! UINavigationController).popToRootViewController(animated: false)
                //
                // I just added extra line so the scroll bar won't annoy you.
                

                【讨论】:

                  【解决方案13】:

                  Xcode 11.5、Swift 5:

                  您不需要使用两个委托方法。一个就够了:

                  extension CustomTabBarController: UITabBarControllerDelegate {
                      func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
                          if tabBarController.viewControllers?.firstIndex(of: viewController) == tabBarController.selectedIndex,
                              let navigationController = viewController as? UINavigationController {
                              navigationController.popToRootViewController(animated: true)
                          }
                      
                          return true
                      }
                  }
                  

                  【讨论】:

                    【解决方案14】:
                    //create a tabbar controller class set it to your TabbarController in storyboard
                    import UIKit
                    
                    class MyTabbarViewController: UITabBarController,UITabBarControllerDelegate{
                    
                        override func viewDidLoad() {
                            super.viewDidLoad()
                            self.delegate = self
                        }
                        
                     
                        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController)
                        {
                            if let vc = viewController as? UINavigationController
                            { vc.popToRootViewController(animated: false) }
                        }
                    
                      
                    
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 2020-06-26
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-10-31
                      • 1970-01-01
                      相关资源
                      最近更新 更多