【问题标题】:Passing Data between view Controllers Using a segue from a view embedded in a navigation controller to a tabbarcontroller在视图控制器之间传递数据使用从嵌入在导航控制器中的视图到 tabbarcontroller 的 segue
【发布时间】:2018-09-14 20:42:29
【问题描述】:

我有两个视图,我想将数据从一个视图传递到另一个视图。第一个视图是我想要传递给下一个视图的数据的地方,我们称之为SourceViewController。但是 SourceViewController 嵌入在 NavigationViewController 中,而 secondViewController 让我们称之为 DestinationViewControllerTabViewController 中的 firstView。

我尝试使用来自this question 的答案,但它无法通过导航视图,它只是跳过了整个逻辑。

这是我的代码:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if (segue.identifier == "loginSuccessSugue") {

        if let tab = self.presentingViewController as? UITabBarController,
            let nav = tab.viewControllers?[0] as? UINavigationController,
            let destinationVC = nav.viewControllers.first as? HomeViewController {


             destinationVC.currentBalance = serviceBalance
        }

    }
}

这是HomeViewController

class HomeViewController: UIViewController , UITableViewDelegate,UITableViewDataSource, UICircularProgressRingDelegate{

var currentBalance = 0.0

 override func viewDidLoad() {
    super.viewDidLoad()

    circularBalance.maxValue = CGFloat(currentBalance)
     print(currentBalance)

   }

  override func viewDidAppear(_ animated: Bool) {
    print(currentBalance)
    circularBalance.setProgress(value: CGFloat(currentBalance), animationDuration: 3)

     }
}

故事板是这样的:

【问题讨论】:

  • 你要介绍你的第二个 VC 吗?
  • 对不起,我刚刚重新检查了我正在使用当前模态 segue,如果这就是你的要求
  • 你没有在你的应用中使用任何 TabBar 对吗?
  • 是的,我正在使用标签栏
  • 所以 HomeViewController 是你的目标 VC 吗?

标签: swift storyboard segue uistoryboardsegue


【解决方案1】:

这是我的视图控制器,您可以在其中检查我是否将 5 发送到标签栏第一个视图控制器:

   class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.performSegue(withIdentifier: "segueIdentifier", sender: self)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let barViewControllers = segue.destination as! UITabBarController
        let destinationNv = barViewControllers.viewControllers?[0] as! UINavigationController
        let destinationViewController = destinationNv.viewControllers[0] as! FirstViewController
        destinationViewController.currentBalance = 5
    }
}

现在您可以检查我的 firstview 控制器,您可以在其中检查我们得到了什么值。

class FirstViewController: UIViewController {

    var currentBalance = 0
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        print(currentBalance)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

现在,您可以查看我的控制台和情节提要:

【讨论】:

    【解决方案2】:

    来自 Apple 的 UIViewController 文档:

    var presentingViewController: UIViewController?

    呈现此视图控制器的视图控制器。

    这对你很有用,** IF ** 你正试图回到你的导航层次结构中,就像 SO post you referenced 中的那个人一样。

    您正在尝试将 SourceViewControllerVC THAT PRESENTED SOURCEVIEWCONTROLLER 转换为 UITabBarController,这会严重失败,这就是为什么您永远不会在嵌套的 if let 中遇到断点的原因.

    如果我们在docs 中向下查看下一个变量,我们可以看到一些将我们带到我们正在呈现的UIViewController 的东西:

    var presentViewController: UIViewController?

    由这个视图控制器呈现的视图控制器,或者一个 它在视图控制器层次结构中的祖先。

    所以现在复习一下解决困境所需的代码。我会给你你发布的相同代码,但修正我在 cmets 中动词的时态:

     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "loginSuccessSugue") {
    
                                   //ing -> ed
            if let tab = self.presentingViewController as? UITabBarController,
                let nav = tab.viewControllers?[0] as? UINavigationController,
                let destinationVC = nav.viewControllers.first as? HomeViewController {
    
    
                 destinationVC.currentBalance = serviceBalance
            }
    
        }
    

    当英语比 swift 更能欺骗你时,这不是令人沮丧吗?

    编辑:

    由于您在prepareForSegue: 中传递数据,因此您实际上希望从segue.destination 获取UITabBarController。并且由于 UITabBarControllerViewControllers 属性将为 nil 或为空,以便为 segue 做准备。这是传递数据的不好方法。

    您可能需要创建UITabBarController 的自定义子类,将变量传递给它,然后将该数据传递给viewDidLoad 中的viewControllers

    class MyTabBarController: UITabBarController {
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
        var serviceBalance : Double?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            //Make sure vc is not null or empty before continuing.
            guard let vcs = viewControllers, !vcs.isEmpty else {
                return
            }
            if let navVC = vcs[0] as? UINavigationController, let destinationVC = navVC.viewControllers[0] as? UIViewController {
                destinationVC.serviceBalance = destinationVC
            }
        }
    }
    

    更新prepareForSegue:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    
        if let tabBarVC = segue.destination as? MyTabBarController {
            tabBarVC.serviceBalance = serviceBalance
        }
    }
    

    别忘了把storyboard的身份检查器中UITabBarController的类改成MyTabBarController

    【讨论】:

      【解决方案3】:

      您需要更改if()条件码。

      使用下面的代码将使您的HomeViewController 到达segue 的目的地。

      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
              if (segue.identifier == "loginSuccessSugue") {
                  if let destinationVC = segue.destination as? HomeViewController {
                      destinationVC.currentBalance = serviceBalance
                  }
              }
          }
      

      segue.destination 一样,您将获得您的HomeViewController,因此无需从Tab + Navigation 堆栈中获取它。

      编辑:

      let destinationVC = segue.destination as? HomeViewController
      Print(destinationVC)
      

      希望这个解决方案会有所帮助!

      【讨论】:

      • 我试过了,但它不起作用。这是我从 HomeViewController 使用 currentBalance 的方式。 override func viewDidAppear(_ animated: Bool) { print(currentBalance) circularBalance.setProgress(value: CGFloat(currentBalance), animationDuration: 3) }
      • 所以你的意思是说你没有在你的家庭 vc 中获得 currentBalance ?或者您无法将其设置为进度条?
      • 是的,我无法在 HomeViewController 中获得余额。即使我在 viewdidload 中打印它
      • 哦,好的,你能在主屏幕上显示你的 var currentBalance 吗?
      • 我已经更新了关于这个问题的 HomeViewController 的代码
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-23
      • 2012-07-17
      • 2023-02-20
      相关资源
      最近更新 更多