this topic is a classical issue in iOS development, and its solution is various as other example already shown. In this example I'll show another daily common use one: passing data using closure
by adapting delegate pattern
example on this page into callback closure
!
one thing this method is superior to delegate pattern
is instead of split the setting up code in two different place( look at delegate example on this page, prepareForSegue
,userDidEnterInformation
) rather gathering them together( only in prepareForSegue
, I'll show it )
Start from Second View Controller
we must figure out how to use callback, then can we write it, this is why we start from second view controller since it's where we use callback: when we got the new text input, we call our callback, using callback's parameter as a medium to passing data back to first ViewController, notice that I said using callback's parameter, this is very important, novices(as I was) always overlook this and don't know where to start to write callback closure properly
so in this case, we know that our callback only take one parameter: text and its type is String
, let's declare it and make it property since we need populate from our first view controller
I just comment all the delegate
part and keep it for comparing
class SecondViewController: UIViewController {
//weak var delegate: DataEnteredDelegate? = nil
var callback: ((String?)->())?
@IBOutlet weak var textField: UITextField!
@IBAction func sendTextBackButton(sender: AnyObject) {
//delegate?.userDidEnterInformation(textField.text!)
callback?(input.text)
self.navigationController?.popViewControllerAnimated(true)
}
}
Finish first view controller
all you have to do is passing callback closure, and we are done, closure will do the future work for us since we already set it up in second view controller
look how it make our code shorter compared to the delegate pattern
//no more DataEnteredDelegate
class FirstViewController: UIViewController {
@IBOutlet weak var label: UILabel!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showSecondViewController" {
let secondViewController = segue.destinationViewController as! SecondViewController
//secondViewController.delegate = self
secondViewController.callback = { text in self.label.text = text }
}
}
// required method of our custom DataEnteredDelegate protocol
//func userDidEnterInformation(info: String) {
// label.text = info
//}
}
and in the last, maybe someone of you will confused by the looking that we only passing the data(closure in this case) only in one way, from first view controller to second, no directly coming back from second view controller, how can we consider it as a communicating tool? maybe you really should run it and prove it yourself, all I will say it's parameter, it's callback closure's parameter that passing data back!