I have created simple Protocol Delegate to pass data from One View Controller to Second View Controller - but data seems to be not carried across?
Details: First View Controller have a textField where I type my data (String) to be passed to Second VC. I also have a button with Action to trigger transition to Second View Controller. Second View Controller comes up but data from First View Controller does not show up - expected behaviour was for the Label in Second VC to be updated with my data from First VC. I also have created a segue from Button on FVC to SVC with the identifier ' sendDataIdentifier '.
What I'm doing wrong?
Code and screenshots below:
First View Controller
import UIKit
protocol SendDataDelegte {
func sendData(data: String)
}
class FirstViewController: UIViewController {
var delegate: SendDataDelegte? = nil
@IBOutlet weak var dataCaptured: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func sendDataButton(_ sender: Any) {
let dataToBeSent = self.dataCaptured.text
self.delegate?.sendData(data: dataToBeSent!)
}
}
Second View Controller
import UIKit
class SecondViewController: UIViewController, SendDataDelegte {
@IBOutlet weak var dataRetrived: UILabel!
@IBAction func closeButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
func sendData(data: String) {
self.dataRetrived.text = data
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "sendDataIdentifier" {
let firstVC: FirstViewController = segue.destination as! FirstViewController
firstVC.delegate = self
}
}
}
You have it the wrong way around.
You don't need a delegate pattern in this instance. You need to implement prepare(for segue)
in the first view controller and just pass the data to the destination view controller.
prepare(for segue)
isn't called in the destination view controller and the delegate
property will be nil
in the first view controller because nothing is setting it.
class FirstViewController: UIViewController {
@IBOutlet weak var dataCaptured: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let dest = segue.destination as? SecondViewController {
dest.text = self.dataCaptured.text
}
}
}
class SecondViewController: UIViewController {
@IBOutlet weak var dataRetrived: UILabel!
var text: String?
@IBAction func closeButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated:Bool) {
super.viewWillAppear(animated)
self.dataRetrieved.text = text
}
}
To push data forward, you can use present method
And to send data backward use delegate.
First Screen
import UIKit
protocol SendDataDelegte: class {
func sendData(data: String)
}
class FirstViewController: UIViewController, SendDataDelegte {
var dataCaptured: UITextField = {
let txt = UITextField()
txt.translatesAutoresizingMaskIntoConstraints = false
txt.backgroundColor = .lightGray
return txt
}()
var sendDataButton: UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.backgroundColor = .lightGray
return btn
}()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
@objc func sendDataButtonAction() {
let dataToBeSent = self.dataCaptured.text
let vc = SecondViewController()
vc.delegate = self
vc.getDataLabel.text = dataToBeSent
vc.modalPresentationStyle = .popover
present(vc, animated: true, completion: nil)
}
func sendData(data: String) {
sendDataButton.setTitle(data, for: .normal)
}
func setupUI() {
view.backgroundColor = .blue
view.addSubview(dataCaptured)
dataCaptured.widthAnchor.constraint(equalToConstant: 200).isActive = true
dataCaptured.heightAnchor.constraint(equalToConstant: 100).isActive = true
dataCaptured.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
dataCaptured.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
view.addSubview(sendDataButton)
sendDataButton.setTitle("Send Data", for: .normal)
sendDataButton.titleColor(for: .normal)
sendDataButton.widthAnchor.constraint(equalToConstant: 200).isActive = true
sendDataButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
sendDataButton.topAnchor.constraint(equalTo: dataCaptured.bottomAnchor, constant: 50).isActive = true
sendDataButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
sendDataButton.addTarget(self, action: #selector(sendDataButtonAction), for: .touchUpInside)
}
}
Second Screen
import UIKit
class SecondViewController: UIViewController {
weak var delegate: SendDataDelegte?
var getDataLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
return lbl
}()
var dataCaptured: UITextField = {
let txt = UITextField()
txt.translatesAutoresizingMaskIntoConstraints = false
txt.backgroundColor = .lightGray
return txt
}()
var sendDataButton: UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.backgroundColor = .lightGray
return btn
}()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
@objc func sendDataButtonAction() {
let string = dataCaptured.text!
delegate?.sendData(data: string)
dismiss(animated: true, completion: nil)
}
func setupUI() {
view.backgroundColor = .yellow
view.addSubview(getDataLabel)
getDataLabel.backgroundColor = .lightGray
getDataLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
getDataLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
getDataLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
getDataLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
view.addSubview(dataCaptured)
dataCaptured.widthAnchor.constraint(equalToConstant: 200).isActive = true
dataCaptured.heightAnchor.constraint(equalToConstant: 100).isActive = true
dataCaptured.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
dataCaptured.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
view.addSubview(sendDataButton)
sendDataButton.setTitle("Send Data", for: .normal)
sendDataButton.titleColor(for: .normal)
sendDataButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
sendDataButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
sendDataButton.topAnchor.constraint(equalTo: dataCaptured.bottomAnchor, constant: 50).isActive = true
sendDataButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
sendDataButton.addTarget(self, action: #selector(sendDataButtonAction), for: .touchUpInside)
}
}
When we call present method on first screen, we send data to second screen's label and assign delegate to self.
When we tap button on second screen, we call delegate method and send text to button title on first screen.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.