Hello,
I'm a beginner with Swift and I'm struggling to understand the way the variables are send between page_1 and page_2 using delegate and protocols.
I have a 2-page application: ViewController1.swift and ViewController2.swift
- on page 1 (ViewController1.swift) I have a textbox (TextBoxControl) and a button.
- on page 2 (ViewController2.swift) I have a label and a button
I want to send text in thextbox from page_1 to page_2 and print it in page_2.
The problem is that the delegated is always nil (it prints on the console
... print ("Delegate is nil"). )
Technologies: XCODE Version 9.4.1, swift 4
How can I solve this?
Thanks in advance.
CODE - page1 ( ViewController1 ):
import UIKit
protocol delegate_transmisie_date_1_2{
func transmisie(text1: String)
}
class ViewController1: UIViewController {
var delegate: delegate_transmisie_date_1_2?
@IBOutlet weak var text1: UITextField!
@IBAction func btn_Send_Date_Using_DelegateAndProtocol(_ sender: Any) {
if self.delegate != nil {
self.delegate?.transmisie(text1: text1.text!)
}else{
print("Delegate is nil")
}
let selectionView = storyboard?.instantiateViewController(withIdentifier: "ID_PAGE2") as! ViewController2
present(selectionView, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
CODE - PAGE2 ( ViewController2 )
import UIKit
class ViewController2: UIViewController, delegate_transmisie_date_1_2 {
@IBOutlet weak var label1: UILabel!
func transmisie(text1: String, text2: String) {
label1.text = text1
}
@IBAction func btn_CloseWindow(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
//This is the place where the delegate must by set ?????
let pagina1 = storyboard?.instantiateViewController(withIdentifier: "ID_PAGINA1") as! ViewController1
pagina1.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Did you try to follow step by step what is described in the link ?
h ttps://medium.com/ios-os-x-development/pass-data-with-delegation-in-swift-86f6bc5d0894
Essentially :
- create a segue between the 2 controllers
- remove all the instantiateViewController
- in prepare for segue, you set the delegate
In fact, it will work differently :
- you will get data from lhe text field of VC1 when you tap a button in VC2,
- if you just want to pass data from VC1 to VC2 when you tap button in VC1, this should be done in the prepare for segue
Here is the code
First embed ViewController1 in a navigation controller (with XCode menu Editor -> Embed in -> Navigation controller
- That will provide a return button from VC2
// FOR ViewController1
You have 2 objects :
a textField text1
a button connected to btn_Send_Date_Using_DelegateAndProtocol
plus a segue to VC2, named VCInitialToVCFinal : control-drag from the button at the very top left of ViewController1 windowController to ViewController2 and select show
import UIKit
protocol delegate_transmisie_date_1_2{
func transmisie() -> String
}
class ViewController1: UIViewController, delegate_transmisie_date_1_2 {
@IBOutlet weak var text1: UITextField!
@IBAction func btn_Send_Date_Using_DelegateAndProtocol(_ sender: Any) { // should better be called performedSegue
performSegue(withIdentifier: "VCInitialToVCFinal", sender: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
// Protocol implementation
func transmisie() -> String {
return text1.text!
}
// Segue : we set the delegate
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? ViewController2 {
destination.delegate = self
}
}
}
// For ViewController2
You have 2 objects
- a button, connected to getDataFromIntial
- a label label1
import UIKit
class ViewController2: UIViewController {
var delegate: delegate_transmisie_date_1_2?
@IBOutlet weak var label1: UILabel! // A label where we write data we get from VC1 when we tap the button
@IBAction func getDataFromInitial(_ sender: UIButton) { // IBAction for a button in VC2, named get data from VC1
let testReadFromVC1 = delegate?.transmisie()
label1.text = testReadFromVC1
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
How to use :
in VC1, type some text in the text field : "This will be read later from VC2"
Then click on the button in VC1
VC2 shows through the segue
Tap on the button in VC2
Then the text you typed in VC1 dispalys in the label
You have effectively transfered data fromVC1 to VC2 through the delegation.
You can also write from ViewController2 to ViewController1 (which now exist when we are in VC2). This is probably more what you are looking for.
Complement protocol:
protocol delegate_transmisie_date_1_2{
func transmisie() -> String
func writeInVC1(text: String)
}
// In ViewController1
add this
func writeInVC1(text: String) {
text1.text = text
}
// In ViewController2
add this
a button "Transfer" connected to an IBAction
an IBOutlet for a textField
@IBOutlet weak var textFieldToTransfer: UITextField!
@IBAction func writeDataToVC1(_ sender: UIButton) { // For Transfer button
let textToWrite = textFieldToTransfer.text!
delegate?.writeInVC1(text: textToWrite)
}