Reputation: 109
I am little bit confuse abt delegation in swift. Say, if I want to pass text of textfield in BViewController to AViewController. (AViewController has a label but I did not put any text, so it shows nothing there) After user done the input and click the "LETS GO" button, text of label in AViewController should show the same text. I implement the code but it gives me some errors. Thanks.
code:
import UIKit
class AViewController: UIViewController, BViewDelegate {
@IBOutlet weak var labelTextData: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func userDoneInput(textData: String) {
labelTextData.text = textData
}
}
import UIKit
protocol BViewDelegate{
func userDoneInput(textData: String)
}
class BViewController: UIViewController {
@IBOutlet weak var UserInputText: UITextField!
var bViewDelegate: BViewDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func LetsGo(_ sender: UIButton) {
self.performSegue(withIdentifier: "ShowData", sender: self)
}
//use segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowData" {
let destination = segue.destination as! AViewController
destination.labelTextData.text = UserInputText.text
}
}
}
Upvotes: 1
Views: 2261
Reputation: 100543
1- A shows
2- When you perform segue to B set delegate here ( this code inside A )
@IBAction func MoveToB (_ sender: UIButton) {
self.performSegue(withIdentifier: "GoToB", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "GoToB" {
let destination = segue.destination as! BViewController
destination.bViewDelegate = self
}
}
3- When you want to return from B to A ( This code inside B )
self.bViewDelegate?.userDoneInput(textData: UserInputText.text!)
self.dismiss(animated:true,completion:nil)
4- There should not be any segue from B to A
Upvotes: 3
Reputation: 93191
It's pretty simple:
A has a label that you can edit in B. There are two buttons that allow you to navigate back and forth. It's important that you don't Ctrl + click on the "Go back to A" button to segue to A. Doing so will add another controller to your hierarchy: A presents B which presents another A. Instead, B should dismiss itself to reveal the original A (see the code below).
//
// AViewController.swift
//
class AViewController: UIViewController {
@IBOutlet weak var label: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "gotoB", let bController = segue.destination as? BViewController {
// Give B a chance to finish loading before using its outlets
bController.loadViewIfNeeded()
bController.textField.text = label.text
bController.delegate = self
}
}
}
extension AViewController: BViewControllerDelegate {
// B says that it has ended. We now update the label in A
func bViewControllerDidEnd(_ controller: BViewController, textValue: String) {
label.text = textValue
}
}
//
// BViewController.swift
//
protocol BViewControllerDelegate {
// For delegate methods, it's customary to pass in the object that triggers this delegate
// (the BViewController), in case you need to make use of its other properties
func bViewControllerDidEnd(_ controller: BViewController, textValue: String)
}
class BViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
var delegate: BViewControllerDelegate?
@IBAction func goBackToA(_ sender: Any) {
// Tell the delegate that "I'm done"
delegate?.bViewControllerDidEnd(self, textValue: textField.text!)
// Dismiss B, not segue to another instance of A
self.dismiss(animated: true)
}
}
Upvotes: 0
Reputation: 67
Firstly, it's best practice not to use a segue to return from A to B (in fact, you are not returning at all, but rather putting a new instance of A over B). There are various options. Here are three:
Before you present B from A, you need to set B's delegate property to be A (you are not doing this at the moment). Then you present B. Then when the user taps "LET'S GO" on B, simply call self.dismiss (or alternative - see options above), but also call self.delegate.userDoneInput(textData:).
Upvotes: 0