【问题标题】:How to segue with data from one Tab to another Tab properly如何正确地将数据从一个选项卡转移到另一个选项卡
【发布时间】:2015-07-03 12:47:16
【问题描述】:

我有一个选项卡栏控制器,它是初始视图控制器,它还有一个PFLoginViewController,如果用户未登录,它会弹出。登录/注册流程工作正常。

这两个标签是 1. UICollectionView 从现在开始我将其称为IntroVC 2. 一个UITableView,我将其称为FeedVC

当用户点击IntroVC 中的照片时,会触发显示转场(通过prepareForSegue),显示第三个屏幕(UIView),这在技术上不是标签。从现在开始,我将把它称为SelectVC

注意:所有这些屏幕也嵌入(ded)在导航控制器中。

SelectVC 显示一张照片,用户可以按下一个UIButton,触发 Show segue 和 Unwind segue,将图像推送到FeedVC。我创建 Unwind segue 的原因是因为没有它,图像会推入FeedVC(第二个选项卡),但第一个选项卡仍会突出显示。

我用 Unwind segue 解决了这个问题,但我注意到我在选择后遇到问题,当我按下第一个选项卡(Intro VC)时,导航栏有一个返回按钮,而且我使用的次数越多SelectVC 按钮推送图像,我必须在IntroVC 中按返回的次数越多。我对如何解决这个问题感到非常困惑。很明显,我没有正确连接流程,似乎IntroVC 正在生成多次?

当我在模拟器中通过 segues 时,我在控制台中收到以下消息:

Nested pop animation can result in corrupted navigation bar

Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.

任何帮助将不胜感激!

相关代码如下。

IntroVC.swift

@IBAction func unwindToIntroView(segue: UIStoryboardSegue) {
    self.tabBarController!.selectedIndex = 1


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "showFeedItem" {
        let selectScreenVC = segue.destinationViewController as! SelectScreenViewController
        let cell = sender as! UICollectionViewCell
        if let indexPath = self.collectionView!.indexPathForCell(cell) {
            self.navigationController?.popViewControllerAnimated(true)
            selectScreenVC.currentVenue = venueItems[indexPath.row]
        }
}

SelectVC.swift

@IBAction func pushSelection(sender: UIButton) {
    var feedItem = FeedItem()
    if let currentItem = currentItem {
        feedItem.nName = currentItem.nName
        feedItem.imageFile = currentItem.lgImg
        feedItem.userName = PFUser.currentUser()!.username!
        feedItem.saveInBackgroundWithBlock({ (success: Bool, error: NSError?) -> Void in
            self.performSegueWithIdentifier("unwindToVenueView", sender: self)
        })
    }
}

我知道这是一个奇怪的结构,如果我缺少完全理解所需的信息 - 请告诉我,我会相应地进行编辑。

【问题讨论】:

    标签: ios uitabbarcontroller segue uistoryboardsegue unwind-segue


    【解决方案1】:

    使用数据转到另一个选项卡

    此解决方案使用展开转场切换到新选项卡并向其发送数据。

    • 绿色是 Tab 1
    • 蓝色是 Tab 1 的后代
    • 黄色是 Tab 2

    目标:从蓝色变为黄色并同时传递数据。

    代码

    蓝色视图控制器(标签 1 的后代)

    import UIKit
    class BlueViewController: UIViewController {
    
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    
            // this is the data that we want to send
            let myData = "Hello from Blue"
    
            // Get a reference to the destination View Controller
            // and set the data there.
            if let yellowVC = segue.destination as? YellowViewController {
                yellowVC.data = myData
            }
        }
    }
    

    黄色视图控制器(选项卡 2)

    import UIKit
    class YellowViewController: UIViewController {
    
        var data: String?
    
        @IBOutlet weak var dataLabel: UILabel!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            updateUI()
        }
    
        @IBAction func comingFromBlueUnwindSegue(segue: UIStoryboardSegue) {
            // This may get called before the UI views have been loaded if
            // the user has not navigated to this tab before. So we need to make
            // sure that the label has been initialized. If it hasn't then we
            // will have our chance to call updateUI() in viewDidLoad().
            // We have to call it here too, though, becuase if the user has
            // previously navigated to this tab, then viewDidLoad() won't get
            // called again.
            if dataLabel != nil {
                updateUI()
            }
        }
    
        func updateUI() {
            // only update the label if the string data was previously set
            guard let myString = data else {return}
            dataLabel.text = myString
        }
    }
    

    界面生成器

    控件从按钮拖动到源视图控制器顶部的退出图标。由于我们已经将展开转场代码添加到目标视图控制器,它将显示为一个选项。选择它。

    注意事项

    • 感谢 this answer 让我走上正轨。
    • 您还可以通过将控件从“退出”图标拖动到“视图控制器”图标来设置展开转场。然后你可以以编程方式调用 segue。详情请见this answer
    • 没有为 Tab 1 视图控制器显示的特殊代码。

    【讨论】:

      【解决方案2】:

      我认为您的问题出在这一行(prepareForSegue 方法)

      self.navigationController?.popViewControllerAnimated(true)
      

      因为您试图在呈现 SelectVC 之前从堆栈中弹出视图控制器。这很可能是导航栏损坏的原因(如果弹出根视图控制器怎么办?)。您可以尝试以下方法:

      self.navigationController?.popToRootViewControllerAnimated(true)
      

      【讨论】:

      • 嘿@flizana,我尝试了你的建议,但不幸的是这没有奏效。感谢您的帮助!
      • 您是否尝试在每个调用的方法中设置断点以检查哪一行引发了异常?
      【解决方案3】:

      我不确定我是否理解您在 IntroVC.swift 的 prepareForSegue: 中调用 self.navigationController?.popViewControllerAnimated(true) 的原因:这样您甚至在呈现之前就将 ViewController 从堆栈中“弹出”(这意味着您实际上尝试弹出 IntroVC出栈,而不是 SelectVC)。

      我要尝试的第一件事是在 prepareForSegue: 中注释该行,看看会发生什么。

      我现在不能尝试,但如果在 SelectVC.swift 中调用 self.performSegueWithIdentifier("unwindToVenueView", sender: self) 会自动触发自身的弹出,我不会感到惊讶,而无需手动调用它。如果不是这样,您可以在 SelectVC.swift 的 pushSelection: 中添加 popViewControllerAnimated(或者可能是 popToRootViewControllerAnimated)。

      让我知道这是否有效!

      祝你有美好的一天,

      @cdf1982

      【讨论】:

      • 嗨@cdf1982 感谢您的建议。我尝试了您的建议,但不幸的是它们没有奏效。我缺少一些东西,但我不知道是什么。再次感谢您的宝贵时间!
      • 别提了。最后的建议:尝试在 unwind 方法中注释 self.tabBarController!.selectedIndex = 1 :记录的错误抱怨完成导航时出现意外状态。可能是因为过早地改变了 VC,即使不是,您也可能希望在代码中添加断点并逐步执行以了解提示这两个错误的原因。祝你好运!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多