I'm new to programming & Swift and I am trying to understand how to pass data between two view controllers (no segue) with protocols and delegates.
I have a View Controller (VIEW A) which has a text field and button. When the user hits that button, it should then show that text in a label in another View Controller (VIEW B).
I cannot get the label to show the text - I would appreciate an explanation of what is required to make this work.
Thanks so much!
import UIKit
protocol sendNameToViewB {
func showNameLabel(name:String)
}
class ViewA: UIViewController {
var delegate: sendNameToViewB?
@IBOutlet weak var textField: UITextField!
@IBAction func addButton(sender: AnyObject) {
delegate?.showNameLabel(textField.text)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
class ViewB: UIViewController, sendNameToViewB {
@IBOutlet weak var theLabel: UILabel!
func showNameLabel(name: String) {
theLabel.text = name
}
}
Protocol: A set of methods that would be implemented by the class which conforms to that protocol. Delegate: The reference to that class which conforms to the protocol and will adhere to implement methods defined in the protocol.
In Swift, declaring a delegate property is just like declaring any other property and you specify the protocol name as the type of the property. You may notice the question mark syntax which indicates that it's a property with an optional value (there may or may not be an object assigned to it).
Delegation is used for everything from handling table view events using UITableViewDelegate , to modifying cache behavior using NSCacheDelegate . The core purpose of the delegate pattern is to allow an object to communicate back to its owner in a decoupled way.
Delegates are a use of the language feature of protocols. The delegation design pattern is a way of designing your code to use protocols where necessary. In the Cocoa frameworks, the delegate design pattern is used to specify an instance of a class which conforms to a particular protocol.
First, a note: Your names for view controllers should include "ViewController" in the name. There is an entirely different collection of classes that inherit from UIView
. Naming a View Controller just ViewA
makes it look like your class is just a view instead of a view controller. Views are in an entirely different layer of your application.
Now, to pass data to another object, your first requirement is to have a reference between them. This reference can be setup in either direction.
One possibility is to have ViewControllerA keep a reference to ViewControllerB. Through this reference, ViewControllerA can call a method on ViewControllerB when the button is pressed which takes that data you want to pass as an argument.
class ViewControllerA: UIViewController {
@IBOutlet weak var viewControllerB: ViewControllerB!
@IBAction func addButton(sender: AnyObject) {
self.viewControllerB.showNameLabel(textField.text)
}
}
The other possibility, is to use a delegate pattern like your title suggests. This would involve ViewControllerB having a reference to ViewControllerA. Preferably, this would not be with direct knowledge of the ViewControllerA class, but instead through a protocol. The protocol would define a method that returns the data you want to "pass" to ViewControllerB. That way, ViewContollerB can call the protocol method on its "delegate" (which would happen to be ViewControllerA) to get the data it needs.
protocol ViewControllerBDelegate {
func requiredText() -> String
}
class ViewControllerB: UIViewController {
@IBOutlet weak var delegate: ViewControllerBDelegate?
override func viewDidLoad() {
if let actualDelegate = self.delegate {
self.theLabel.text = actualDelegate.requiredText()
}
}
}
Which method you choose really depends on what you need in this circumstance. The delegate pattern is better to keep your objects less coupled together, but if you are already needing to "trigger" things to happen on ViewControllerB from ViewControllerA then the more direct method is probably required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With