简体   繁体   中英

Assigning a delegate from a non parent View Controller

I'm struggling a little with Protocols and Delegates in Swift 4. I'm going to do my best to describe / show you what I have.

Main View Controller: (MVC) 1. I have the Main Viewcontroller class (MVC). The VC has a property of options that I would like to access from another ViewController Class (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. I have a View Controller class Statement ViewController (SVC) that is called from the (MVC). I am using prepare for segue func to set this view controller up for (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. I have a third View Controller class AddStatement View Controller (AVC) which is called from (SVC). I am also using prepare for segue func to set this view controller up as well from (SVC)

This class has a protocol that I define in (MVC).

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

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

Where I am confused is where to set the delegate property. The examples I have seen seem to set the delegate property in the prepare for seguer func. But since the (MVC) is the one that is conforming to the FormateStatementDelegate protocol where and how would I set the delegate in the (AVC) since they do not have a parent / child relationship. I hope I've explained this in a meaningful way.

Your delegate is declared as an implicitly unwrapped optional:

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

Be careful with that. If you forget to set the delegate, the app will crash. There's also potential for a strong retention cycle causing memory leak. The general pattern I use is to declare it as a weak optional:

protocol FormateStatementDelegate: class {
    ...
}

class AddStatementViewController: UIViewController{
    weak var delegate: FormateStatementDelegate?

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

Now on to your problem: If I understand your problem description correctly, the segue order is like this:

ViewContorller -> StatementViewController -> AddStatementViewController

And AddStatementViewController has a delegate, which ViewController conforms to. You simply need to hold a reference to the instance of MainViewController in the second view controller:

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
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM