【问题标题】:Swift - Use segmented control to navigate to different view controllersSwift - 使用分段控制导航到不同的视图控制器
【发布时间】:2014-11-20 21:10:48
【问题描述】:

我有一个在 navController 中嵌入了 mapViewController 的应用程序。在 mapVC 中,我有一个单条按钮项,单击该按钮项时,我想有条件地“推送”segue 到多个不同视图控制器之一。为了实现这一点,我在按钮上设置了一个 ibaction,并在相关按钮 ibaction 方法中有条件“performSegueWithIdentifier”代码,即

    @IBAction func addButtonClicked(sender: UIBarButtonItem) {
    let lastAdd = "addItem"
    if lastAdd == "addItem"{
        self.performSegueWithIdentifier("addItem", sender: self)
    } else {
        self.performSegueWithIdentifier("addEvent", sender: self)

    }
}

这将带我到 addItemVC 或 addEventVC。在每个视图控制器(即 addItemVC 和 addEventVC)中,我希望在导航栏中有一个分段控件,当单击该控件时,它将带我到替代 VC,即如果当前显示 addItemVC,以及分段的 addEvent 部分单击控件时,我想显示 addEventVC。我正在关注Red Artisans page 如何执行此操作,但在他的示例中,他在应用程序委托中预先实例化所有视图控制器选项,因此可以轻松获取对每个视图控制器的引用并将其链接到其 rootVC 中分段控件的单击段

我感到困惑的是......在执行每个 segue 之前看到我使用条件代码,我假设我只在按下条形按钮项时实例化一个 viewController。那么我怎样才能让一组视图控制器传递给 VC 即时通讯,以便我可以在该 VC 中创建所需的分段控件。我假设我可以在我的 mapViewController 中手动创建目标 VC 数组并传递它们,但这是否意味着我将一个不同的实例实例化为由 segue 进程自动创建的实例?

【问题讨论】:

    标签: ios swift uinavigationbar uisegmentedcontrol


    【解决方案1】:

    是的,您是对的:如果您在 mapViewController 中手动创建两个 VC,它们将是与 segue 创建的不同的实例。因此,如果您想坚持 Red Artisan 的解决方案,请使用代码而不是 segues 来展示 VC。您仍然可以在情节提要中设计这两个 VC,为它们分别指定一个唯一标识符,然后使用 self.storyboardinstantiateViewControllerWithIdentifier 函数创建实例。

    您可以在 mapViewController 中使用 Red Artisan 的大部分应用程序委托代码,但需要进行一些调整:例如。使用现有的导航控制器(其中嵌入了您的 mapViewController),并且 [window ...] 行是多余的。需要注意的是indexDidChangeForSegmentedControl 函数,它假定您正在切换的VC 是导航控制器的rootViewControllers(即它们是导航控制器viewControllers 数组中的唯一项)。在您的情况下,您将 mapViewController 作为(我假设)rootViewController,因此您必须修改 indexDidChangeForSegmentedControl 函数以创建一个数组,其中 mapViewController 位于索引 0,相关(addItem 或 addEvent)VC 位于索引 1。我不'不知道这个方法的动画效果如何,也不知道后退按钮等是否正确设置。

    如果您想坚持使用 segue,有两种解决方案:一种是使用 UITabBarController(并隐藏 tabBar)。您可以将 addItem 和 addEvent VC 作为单独的选项卡,当您选择 tabBarController 时,您可以设置选择哪个选项卡。但我首选的解决方案是继续使用UIPageViewController。您可以在 mapViewController 中创建 VC 并将它们作为 segue 的一部分传递,或者只传递一个关于哪个被选中的指示符,并让 pageViewController 实例化它们并呈现相关的。然后您可以使用UISegmentedControl 触发VC 之间的切换。请参阅this answer 了解类似内容。

    【讨论】:

      【解决方案2】:

      感谢 pbasdf 的详细说明。它花了我一段时间,但我似乎接近让它工作了。我遵循了您的大部分指示,并且您对您所说的话很了解。

      首先从 mapVC 中按下 + 栏按钮项,我使用 instantiateViewControllerWithIdentifier 创建 addItem 和 addEvent VC,并创建分段控件。

          @IBAction func addButtonClicked(sender: UIBarButtonItem) {
      
          //at this stage just manually set default target VC
          let lastAdd = "addItem"
      
          //get an array of the target viewcontrollers
          var viewControllers = segmentViewControllers()
      
          //initz the segmentscontoller with the current navcontroller if doesnt already exist 
          if segmentsController == nil {
              segmentsController = SegmentsController(navController: self.navigationController!, viewControllers: viewControllers)
              segmentedControl.addTarget(segmentsController, action: "indexDidChangeForSegmentControl:", forControlEvents: UIControlEvents.ValueChanged)
              //add the segmented control to the VC by setting first user experience which calls indexdidchangeforsegmentedcontrol
              firstUserExperience()
          }
          segmentsController?.indexDidChangeForSegmentControl(segmentedControl)
      
      }
      
          //create an array of the target view controller. called from addbutton clicked
      func segmentViewControllers() -> [UIViewController] {
      
          //create an instance of the viewcontrollers
          let addItemVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("AddItemVC") as ViewController
          let addEventVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("AddEventVC") as ViewController
      
          var viewControllers = [addItemVC, addEventVC]
      
          return viewControllers
      }
      

      在segmentsController 中,我创建了2 个数组,1 个用来保存不同的VC,1 个用来保存导航堆栈。我还将传递的分段控制设置给传入的 VC

      class SegmentsController: NSObject {
      
      var navController: UINavigationController?
      var viewControllersOptionsArray: [UIViewController] = []
      var viewControllersNavArray: [UIViewController] = []
      
      
      //MARK: - INITIALIZER
      init(navController: UINavigationController, viewControllers: [UIViewController]) {
      
          self.navController = navController
          self.viewControllersOptionsArray = viewControllers
      }
      
      
      //MARK: SEGMENT INDEX METHOD
      func indexDidChangeForSegmentControl(segmentedControl: UISegmentedControl) {
      
          var index = segmentedControl.selectedSegmentIndex
          var incomingViewController = viewControllersOptionsArray[index]
      
          //set the viewControllersNavArray
          if let mapVC = navController?.viewControllers[0] as? MapViewController {
              viewControllersNavArray = [mapVC, incomingViewController]
          }
      
          //set the navcontroller with a new array of viewcontrollers
          navController?.setViewControllers(viewControllersNavArray, animated: true)
      
          //set the title of the incoming view controller
          incomingViewController.navigationItem.titleView = segmentedControl
      
          //set the seg control variable of the incoming VCs
          if let iVC = incomingViewController as? AddItemViewController {
              iVC.segmentedControl = segmentedControl
          } else if let iVC = incomingViewController as? AddEventViewController {
              iVC.segmentedControl = segmentedControl
          }
      }
      

      }

      在 addItem 和 addEvent VC 中,我认为如果用户按下后退按钮,我需要将当前 selectedSegmentIndex 传递回 mapVC - 不确定如何执行此操作并最终使用我下载的名为 UIViewController+BackButtonHandler 的扩展来处理它。

      我确信我的代码可以写得更好,但我唯一仍然遇到的问题是我希望 VC 转换具有动画效果。如果我在 navController?消失。它仍然在那里,所以我仍然可以导航,但你看不到它。我认为这与在视图正确加载之前设置它有关,但即使我将代码设置为即

      incomingViewController.navigationItem.titleView = segmentedControl
      

      在 viewDidLoad 或 viewDidAppear 的新顶级 VC 中,我仍然遇到同样的问题。我还认为如果我可以将incomingViewController.navigationItem.titleView = segmentedControl 代码放在完成块中,但setViewControllers 方法似乎没有完成处理程序,我可能能够修复它。 有什么建议吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-25
        • 1970-01-01
        • 2014-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多