问题
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")
}
}
来源:https://stackoverflow.com/questions/54782250/how-can-we-pass-the-closures-to-any-viewcontroller-in-the-app-flow