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?
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")
}
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")
}
}