如何从多个故事板源视图控制器呈现给定的视图控制器?

时间:2017-03-16 23:19:01

标签: ios swift3 xcode8 uistoryboard

我正在编写一个故事板,我需要提供一个数据输入视图控制器。数据输入vc需要一个保存按钮和一个取消按钮。我需要从其他两个视图控制器中提供数据输入vc。

我想通过故事板配置它,以便我的故事板确实“讲故事”。如果我对数据条目VC执行show segue,那么后退按钮将使我回到正确的源控制器(VC1或VC2)。我想我可以使用后退按钮来触发取消操作(嗯...),但那么保存操作呢?如果我通过中间导航控制器以模态方式呈现数据条目VC,那么我可以添加保存和取消栏按钮项目并附加展开segue到它们,但似乎没有办法有条件地放松回正确的源( VC1或VC2)。

我已经确定的是:

  1. VC1和VC2将模态地显示数据条目VC而没有介入的导航控制器(即没有数据条目VC的导航项)。
  2. 数据输入vc将有两个UIButton,保存和取消。这两个按钮将触发数据输入VC中的操作,这将取消它。
  3. VC1(VC2)会将目标添加到数据条目VC的按钮,以便VC1(VC2)可以采取适当的操作(包括删除目标)。
  4. 请参阅下面的代码和故事板。 (注意:这些不是来自我的实际应用。它们来自我用来试验的项目。)

    所以,我的作品。但是,我不禁觉得有一种更优雅的技术。我真正想要的是重用数据输入视图及其控制器。从所有者是数据输入vc的笔尖加载视图会起作用吗?也许是UIContainerView?有更多经验的人请告诉我(如果甚至确认我拥有的是什么就好了)?谢谢!

    VC1和VC2中的相关代码:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    
        func setupButtons(_ view: UIView) {
            view.subviews.forEach() { view in
                if let button = view as? UIButton, let title = button.title(for: .normal) {
                    switch title {
                    case "Save":
                        button.addTarget(self, action: #selector(save(sender:)), for: .touchUpInside)
                    case "Cancel":
                        button.addTarget(self, action: #selector(cancel(sender:)), for: .touchUpInside)
                    default:
                        break
                    }
    
                }
                else {
                    setupButtons(view)
                }
            }
        }
    
        if let vc = segue.destination as? DataEntryViewController {
            setupButtons(vc.view)
        }
    
    }
    
    func cancel(sender: UIButton) {
        process(button: sender, save: false)
    }
    
    func save(sender: UIButton) {
        process(button: sender, save: true)
    }
    
    private func process(button: UIButton, save: Bool) {
        let title = button.title(for: .normal) ?? "<unknown>"
        print("The \(title) button was pressed")
    
        if save {
            if let vc = button.viewController as? DataEntryViewController {
                print("The data is \(vc.data)")
            }
            else {
                print("Cannot get the \(title) button's VC")
            }
        }
    
        button.removeTarget(self, action: nil, for: .touchUpInside)
    }
    

    数据输入控制器中的相关代码:

    @IBAction func cancel(_ sender: UIButton) {
        self.dismiss(animated: true, completion: nil)
    }
    
    @IBAction func save(_ sender: UIButton) {
        self.dismiss(animated: true, completion: nil)
    }
    

    enter image description here

1 个答案:

答案 0 :(得分:1)

根据我对放松细分的了解,这应该可行。见Technical Note TN2298 “Unwind Segue如何确定其目标视图控制器”一节。您是否真的尝试在VC1和VC2中实现相同的展开操作 并将按钮连接到Interface Builder中的相应展开操作?

作为旁注,您应该在查看视图时使用标记,而不是将按钮标题与固定字符串(国际化和全部)进行比较。

编辑:

我刚刚创建了一个测试项目,正是我所描述的。该应用程序是一个标签栏控制器,带有两个视图控制器(FirstViewControllerSecondViewController),它们都提供一个带有取消按钮和保存按钮的数据输入视图控制器。它们分别连接到展开动作unwindToCancel:unwindToSave:

Storyboard

Unwind to Cancel

class FirstViewController: UIViewController
{
    @IBAction func unwindToSave(_ segue: UIStoryboardSegue)
    {
        print("FirstViewController unwindToSave")
    }

    @IBAction func unwindToCancel(_ segue: UIStoryboardSegue)
    {
        print("FirstViewController unwindToCancel")
    }
}

class SecondViewController: UIViewController
{
    @IBAction func unwindToSave(_ segue: UIStoryboardSegue)
    {
        print("SecondViewController unwindToSave")
    }

    @IBAction func unwindToCancel(_ segue: UIStoryboardSegue)
    {
        print("SecondViewController unwindToCancel")
    }
}

根据我来自哪个视图控制器,点击取消或保存时会打印正确的信息。