【问题标题】:iOS8 TabbarController inside a UISplitviewController MasterUISplitviewController Master内的iOS8 TabbarController
【发布时间】:2014-10-24 05:10:11
【问题描述】:

我尝试通过在MasterView的UINavigationController前面添加一个UITabbarController来扩展默认的Apple MasterDetail Template,所以有这样一个结构:

UISplitViewController (Master) > UITabbarController > UINavigationController > UITableViewController

但是,如果我运行应用程序,在更改应用程序(didFinishLaunchingWithOptions)以使用正确的 ViewController 之后,并尝试执行 ShowDetails Segue 以在 iPhone 上模态显示 DetailsView。另一方面,iPad 版本按预期工作。 我忘了做什么?或者我该如何解决?

【问题讨论】:

    标签: uitabbarcontroller uisplitviewcontroller ios8


    【解决方案1】:

    我想出了如何将细节放在主人的 UINavigationController 上,而不是在 UITabBarController 上模态地呈现它。

    使用 UISplitViewControllerDelegate 方法

    - splitViewController:showDetailViewController:sender:
    

    如果 UISplitViewController 折叠,获取主导航控制器并将详细视图推送到此导航控制器:

    - (BOOL)splitViewController:(UISplitViewController *)splitViewController
       showDetailViewController:(UIViewController *)vc
                         sender:(id)sender {
        NSLog(@"UISplitViewController collapsed: %d", splitViewController.collapsed);
    
        // TODO: add introspection
        if (splitViewController.collapsed) {
            UITabBarController *master = (UITabBarController *) splitViewController.viewControllers[0];
            UINavigationController *masterNavigationController = (UINavigationController *)master.selectedViewController;
    
            // push detail view on the navigation controller
            [masterNavigationController pushViewController:vc animated:YES];
    
            return YES;
        }
    
        return NO;
    }
    

    【讨论】:

    • 如果您像我在 tableView 中那样使用performSegueWithIdentifier,似乎永远不会调用此方法:didSelectRowAtIndexPath :/ 还有其他想法如何解决这个问题吗?
    • 你设置了splitcontroller的delegate吗?
    【解决方案2】:

    只是为了更新上面的答案。由于您不能再推送导航控制器,因此您必须改为推送其顶视图控制器。

        func splitViewController(splitViewController: UISplitViewController, showDetailViewController vc: UIViewController, sender: AnyObject?) -> Bool {
            if splitViewController.collapsed {
                let tabBarController = splitViewController.viewControllers.first as! UITabBarController
                let selectedNavigationViewController = tabBarController.selectedViewController as! UINavigationController
    
                // Push view controller
                var viewControllerToPush = vc
                if let navController = vc as? UINavigationController {
                    viewControllerToPush = navController.topViewController
                }
                selectedNavigationViewController.pushViewController(viewControllerToPush, animated: true)
    
                return true
            }
    
            return false
        }
    

    【讨论】:

      【解决方案3】:

      这是我的解决方案。放入 MasterViewController.m 并记住在 IB 中为您的详细视图提供 Storyboard ID。就我而言,“细节”。

      -(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
          if ([identifier isEqualToString:@"showDetail"] && self.splitViewController.collapsed) {
              DetailViewController *myController = (DetailViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"detail"];
              NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
              NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
              [myController setDetailItem:object];
              [self.navigationController showViewController:myController sender:self];
               return NO;
          }
          return YES;
      }
      

      【讨论】:

        【解决方案4】:

        还有另一种不用代码的方法。

        在将 UINavigationController 嵌入 TabBarController 后,将 TabBarController 嵌入另一个 UINavigationController。所以你将拥有:SplitViewController -> Master -> NavCon -> TabBar -> NavCon -> TableViewController。

        这样做要容易得多,但是有一个我还没有找到解决方法的错误。呈现的导航栏将是 TabBarController 的导航栏,而不是 TableViewController 的导航栏。任何想法如何解决这个问题?

        【讨论】:

          【解决方案5】:

          像这样子类 TabBarController:

          - (void)showViewController:(UIViewController *)vc sender:(id)sender
          {
              if ([self.selectedViewController isKindOfClass:UINavigationController.class])
                  [self.selectedViewController showViewController:vc sender:sender];
              else
                  [super showViewController:vc sender:sender];
          }
          
          - (UIViewController*)separateSecondaryViewControllerForSplitViewController:(UISplitViewController *)splitViewController
          {
              return [self.selectedViewController separateSecondaryViewControllerForSplitViewController:splitViewController];
          }
          
          - (void)collapseSecondaryViewController:(UIViewController *)secondaryViewController forSplitViewController:(UISplitViewController *)splitViewController
          {
              [self.selectedViewController.navigationController collapseSecondaryViewController:secondaryViewController forSplitViewController:splitViewController];
          }
          

          完整说明请参见this question

          【讨论】:

            【解决方案6】:

            这是基于测试 splitViewController 的大小类的替代方法:

            1. 使用自定义 UISplitViewController(子类)
            2. 覆盖 showDetailViewController 操作
            3. 使用 traitCollection 确定 UISplitViewController 的类
            4. 如果横向类是Compact,让navigationController调用showViewController

            这是自定义 UISplitViewController 的代码:

            import UIKit
            
            class CustomSplitViewController: UISplitViewController {
            
                override func showDetailViewController(vc: UIViewController!, sender: AnyObject!) {
            
                    if (self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact) {
                        if let tabBarController = self.viewControllers[0] as? UITabBarController {
                            if let navigationController = tabBarController.selectedViewController as? UINavigationController {
                                navigationController.showViewController(vc, sender: sender)
                                return
                            }
                        }
                    }
            
                    super.showDetailViewController(vc, sender: sender)
                }
            }
            

            不要忘记在情节提要中设置自定义类。

            在 iPhone 6、iPhone 6+ 和 iPad Air 的模拟器中测试并按预期工作。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-12-23
              • 1970-01-01
              • 2016-04-13
              • 1970-01-01
              • 2015-05-06
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多