未触发自定义 segue 的展开

Posted

技术标签:

【中文标题】未触发自定义 segue 的展开【英文标题】:Unwind of custom segue not triggered 【发布时间】:2016-11-06 15:44:48 【问题描述】:

问题

我的问题是即使单击后退按钮也不会触发展开过程。

我的代码

我有一个 1stViewController 类,它使用自定义 segue 到 2ndViewController。自定义 segue 如下:

override func perform() 
    let sourceVC = self.source as! 1stViewController
    let destinationVC = self.destination as! 2ndViewController
    sourceVC.addChildViewController(destinationVC)
    sourceVC.view.addSubview(destinationVC.view)

在我的 2ndViewController 中,我添加了一个按钮,该按钮可触发返回到 1stViewController 的展开 segue。展开转场通过 2ndViewController 中展开转场触发出口的标识符连接。因此,我创建了一个 IBAction 连接到 unwind segue 出口:

@IBAction func unwindToFeed(segue: UIStoryboardSegue) 

我已将展开转场的标识符设置为与按钮操作函数中使用的标识符相同

func handleActionBackButton()
    print("here")
    self.performSegue(withIdentifier: "unwindId", sender: self)

单击按钮时会打印“Here”,但似乎 performSegue 不是。

我猜我也需要一个自定义的 unwindSegue 类,所以我创建了 unwindSegueEventToFeed:

class unwindSegueEventToFeed: UIStoryboardSegue 

override func perform() 
    let sourceVC = self.source as! 2ndViewController
    let destinationVC = self.destination as! 1stViewController

    let sourceView = sourceVC.view as UIView!
    let destView = destinationVC.view as UIView!

    let window = UIApplication.shared.keyWindow
    window?.insertSubview(destView!, aboveSubview: sourceView!)
    sourceVC.dismiss(animated: false, completion: nil)

...在 2ndViewController 中调用:

override func segueForUnwinding(to toViewController: UIViewController, from fromViewController: UIViewController, identifier: String?) -> UIStoryboardSegue? 
    return unwindSegueEventToFeed(identifier: identifier, source: fromViewController, destination: toViewController)

关于我必须做些什么来触发展开过程的任何线索?

【问题讨论】:

确认一下,unwindToFeed 在 1stViewController 中? unwindToFeed 在 2ndViewController 中 那是错误的地方。 unwind 方法进入你正在展开的视图控制器 to 但是 unwindToFeed 不应该在您想要关闭的视图中吗? 2ndViewController 是按钮所在的用户可见的视图 没有。您可以从任意数量的 VC 展开到 VC,因此展开操作方法为您提供了一个一致的位置来处理展开。您不需要源代码中的展开方法,因为您可以拥有一个简单的按钮操作处理程序,甚至可以直接从 UI 元素触发展开,无需代码。 Apple 有一个很好的关于使用 unwind segues 的技术说明 【参考方案1】:

我让你的例子像这样工作。 ViewController 是第一个视图控制器; ViewController2 是第二个视图控制器:

class ViewController: UIViewController 
    @IBAction func unwindToFeed(_ segue: UIStoryboardSegue) 
        let child = self.childViewControllers[0]
        child.willMove(toParentViewController: nil)
        child.view.removeFromSuperview()
        child.removeFromParentViewController()
    


class MySegue: UIStoryboardSegue 
    override func perform() 
        let sourceVC = self.source as! ViewController
        let destinationVC = self.destination as! ViewController2
        sourceVC.addChildViewController(destinationVC)
        sourceVC.view.addSubview(destinationVC.view)
        destinationVC.view.frame = sourceVC.view.bounds
        destinationVC.view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        destinationVC.didMove(toParentViewController: sourceVC)
    


class ViewController2 : UIViewController 

请注意,unwindToFeed 是(并且必须是)在 first 视图控制器中。放在第二个视图控制器中是没有意义的,因为第二个视图控制器是展开的source,而不是destination

现在我想就这个问题和我的答案做一些cmet:

这是一个 ios 10 示例。 segueForUnwinding永远在 iOS 10 中被调用;它在 iOS 8 之后被废弃,随后被弃用。

segueForUnwinding 的 iOS 9/10 等效项是 unwind(for:towardsViewController:)。我确实尝试过实现它,但我发现它是在 ViewController2 中调用的,而不是在 ViewController 中。我认为这是 iOS 10 中的一个错误,并将其报告给 Apple。

【讨论】:

但是我的示例在 iOS 9 中根本不起作用。一般来说,使用自定义父视图控制器展开 segues 的整个概念看起来仍然很糟糕,就像多年来一样,我建议完全避免它。

以上是关于未触发自定义 segue 的展开的主要内容,如果未能解决你的问题,请参考以下文章

从多个自定义 segue 展开到根控制器时崩溃

从自定义导航栏展开 segue 后,如何切换回默认导航栏外观?

Segue 未从自定义 tableView 单元格触发

自定义 UITableViewCell:以编程方式触发选择 segue

如何从自定义 UITableViewCell 触发 segue - iOS7

在另一个视图控制器展开 segue 后重新加载 UIView 数据上的自定义 tableview