在视图控制器之间传递数据:使用segue从嵌入导航控制器的视图到tabbarcontroller。

5
我有两个视图,我想从一个视图传递数据到下一个视图。第一个视图是我拥有需要传递到下一个视图的数据的地方,让我们称之为SourceViewController。然而,SourceViewController嵌入在一个NavigationViewController中,第二个视图控制器,我们称之为DestinationViewController,是TabViewController中的第一个视图。
我尝试使用这个问题的答案,但它无法通过导航视图,它只是跳过整个逻辑。
这是我的代码:
    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)

     }
}

这是故事板的样子: enter image description here

抱歉,我刚刚重新检查了一下,我正在使用一个现有模态转场,如果这是你所问的。 - DvixExtract
你的应用程序中没有使用任何TabBar,对吗? - CodeChanger
是的,我正在使用一个Tabbar。 - DvixExtract
是的,HomeViewController 是目标。 - DvixExtract
在这个destinationVC.currentBalance = serviceBalance行上设置一个断点,看看这一行是否被执行。 - nayem
显示剩余2条评论
3个回答

5
这是我的视图控制器,你可以检查我是否向选项卡的第一个视图控制器发送了“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
    }
}

现在您可以检查我的第一个视图控制器,在那里您可以查看我们得到了什么值。
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.
    }

}

现在,您可以查看我的控制台和故事板: 图片描述 图片描述

3

来自苹果的UIViewController文档:

var presentingViewController: UIViewController?

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

如果您尝试返回导航层次结构,这将非常适用于您,就像您所引用的SO帖子中的那个人一样。

您正在将SourceViewController呈现源视图控制器VC强制转换为UITabBarController,这会失败,并且这就是为什么您从未在嵌套的if let中触发断点的原因。

如果我们查看文档中的下一个变量,我们可以看到一些将我们前进到我们正在呈现的UIViewController的东西:

var presentedViewController: UIViewController?

这个视图控制器所呈现的视图控制器,或者是它在视图控制器层级中的祖先之一。

现在让我们来看看你需要解决的代码。我会给你相同的代码,但是在注释中修正动词的时态:

 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
        }

    }

当英语比速度更容易让你迷惑时,这不是很令人沮丧吗?

编辑:

由于您在prepareForSegue:中传递数据,因此实际上需要从segue.destination获取UITabBarController。由于在为segue准备时UITabBarControllerViewControllers属性将为nil或为空,因此这是传递数据的不良方法。

您可能需要创建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
    }
}

不要忘记在故事板的身份检查器中将UITabBarController的类更改为MyTabBarController

2

您需要修改if()条件代码。

使用下面的代码将在segue的目标中获取您的HomeViewController

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) } - DvixExtract
那么你的意思是说你在home vc中没有得到currentBalance?还是你无法将它设置到进度条中? - CodeChanger
哎呀,我无法在HomeViewController中获取余额。即使我在viewdidload中打印它。 - DvixExtract
哦,好的,你能在主屏幕上展示一下你的当前余额变量吗? - CodeChanger
请检查他的故事板截图,segue.destination 将是 tabBarController - NSGangster
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接