首页 > 解决方案 > 从非父视图控制器分配委托

问题描述

我在 Swift 4 中的协议和委托方面有点挣扎。我将尽我所能描述/向你展示我所拥有的。

主视图控制器:(MVC) 1. 我有主视图控制器类(MVC)。VC 具有我想从另一个 ViewController 类 (AVC) 访问的选项属性

class ViewController: UIViewController {
var options: Options?


 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
    if (segue.identifier == "To Statements") {
        // pass data to next view
        let vc = segue.destination
        let statementVC = vc as! StatementsViewController
        statementVC.coreDataStack = coreDataStack
        statementVC.currentPerson = currentPerson

    }
}

extension ViewController: FormateStatementDelegate {

   // formatting protocol
   func addStatementFormat() -> Int {
     // here is where I would use the options var that is found in the (MVC)
   }
}

Statement ViewController: (SVC) 2. 我有一个从 (MVC) 调用的 View Controller 类 Statement ViewController (SVC)。我正在使用prepare for segue func来设置这个视图控制器(MVC)。

    class StatementsViewController: UIViewController{

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if (segue.identifier == "Add Statement") {
        // pass data to next view
        //print("segue to add statement")
        let vc = segue.destination
        let addStatementVC = vc as! AddStatementViewController
        addStatementVC.coreDataStack = coreDataStack
        addStatementVC.personName = currentPerson!.name!    
    }
    }

AddStatement View Controller (AVC) 3. 我有第三个 View Controller 类 AddStatement View Controller (AVC),它是从 (SVC) 调用的。我也使用prepare for segue func来设置这个视图控制器以及(SVC)

这个类有一个我在 (MVC) 中定义的协议。

protocol FormateStatementDelegate {
func  func addStatementFormat() -> Intmal
}

class AddStatementViewController: UIViewController{
   var delegate FormateStatementDelegate! = nil
}

我感到困惑的是在哪里设置委托属性。我见过的例子似乎在准备 seguer 函数中设置了委托属性。但是由于 (MVC) 是符合 FormateStatementDelegate 协议的协议,我将在哪里以及如何在 (AVC) 中设置委托,因为它们没有父/子关系。我希望我已经以有意义的方式解释了这一点。

标签: swiftdelegatesswift-protocols

解决方案


您的委托被声明为隐式展开的可选:

class AddStatementViewController: UIViewController{
   var delegate FormateStatementDelegate! = nil
}

小心点。如果您忘记设置委托,应用程序将崩溃。强大的保留周期也可能导致内存泄漏。我使用的一般模式是将其声明为弱可选:

protocol FormateStatementDelegate: class {
    ...
}

class AddStatementViewController: UIViewController{
    weak var delegate: FormateStatementDelegate?

    func doSomething() {
        delegate?.addStatementFormat() // This statement will do nothing if delegate is nil
    }
}

现在解决您的问题:如果我正确理解了您的问题描述,则 segue 顺序如下:

ViewContorller -> StatementViewController -> AddStatementViewController

并且AddStatementViewController有一个代表,它ViewController符合。您只需要MainViewController在第二个视图控制器中保存对实例的引用:

class ViewController: UIViewController {

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
        if (segue.identifier == "To Statements") {
            // pass data to next view
            let vc = segue.destination
            let statementVC = vc as! StatementsViewController
            statementVC.coreDataStack = coreDataStack
            statementVC.currentPerson = currentPerson
            statementVC.formateStatementDelegate = self
        }
    }
}

class StatementViewController {
    weak var formateStatementDelegate: FormateStatementDelegate?

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "Add Statement") {
            // pass data to next view
            //print("segue to add statement")
            let vc = segue.destination
            let addStatementVC = vc as! AddStatementViewController
            addStatementVC.coreDataStack = coreDataStack
            addStatementVC.personName = currentPerson!.name!    
            addStatementVC.delegate = formateStatementDelegate
        }
    }
}

推荐阅读