How can we pass the closures to any ViewController

2019-08-22 02:54发布

问题:

In View Controller A,

var completionBlock: (((String) -> ()))? = nil

& I am calling the completion block like(ViewController A):

if let block = completionBlock {
     block("block data to pass") 
}

I don't want to pass the completion data to ViewController B, instead i want to pass to ViewController C which is presenting from ViewController B.

In simple words, i want to pass the closure data to from ViewController A to ViewController C.I know how to pass data with delegates, just curious with closures?

How can we achieve that?

回答1:

If this block is something that you need to pass between several viewControllers, you have few options:

1- Pass closure as a variable: Create a variable on each new ViewController in the middle of VC-A, VC-C and pass them in between

for example:

//View Controller B:
var block:(((String) -> ()))? = nil

//Pass from A-B
if let viewcontrollerB = XXXX { //instantiate ViewController B from A
    viewcontrollerB.block = self.block
}


//ViewController C:
var block:(((String) -> ()))? = nil

//Pass from B-C
if let viewcontrollerC = XXXX { //instantiate ViewController C from B
    viewcontrollerC.block = self.block
}

//Call the block from ViewController C
if let block = self.block {
   block("block data to pass") 
}

2-Pass via Notification Center You can pass this block from Any View Controller to Any Other:

//send notification:
let notification = Notification(name: Notification.Name("pass block"), object: block, userInfo: nil)
NotificationCenter.default.post(notification)

3-Access from shared object Use a singleton design and create a static shared object and read/write to the object from different view controllers

//AppDelegate:
static var block:(((String) -> ()))? = nil

//ViewController A:
AppDelegate.block = XXX

//ViewController C:
if let block = AppDelegate.block {
   block("block data to pass") 
}


回答2:

This is just a sample code i quickly wrote for you, you can modify objects based on your need. Hopefully will address your problem.

import UIKit

class ViewControllerA: UIViewController {
    var block:(((String) -> ()))? = { input in
        print(input)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "A"
        let VCB = ViewControllerB()
        let VCC = ViewControllerC()
        VCC.block = block
        VCB.VCC = VCC
        self.navigationController?.pushViewController(VCB, animated: true)

    }


}

class ViewControllerB: UIViewController {
    var VCC:ViewControllerC?
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .gray

    }
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        if let VCC = VCC {
            self.present(VCC, animated: true, completion: nil)
        }
    }


}

class ViewControllerC: UIViewController {
    var block:(((String) -> ()))? = nil

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .yellow
        //Will run the block that has been passed
        block?("test")
    }


}