0

I'm recently studying Swift. I create projects of varying complexity, but I still don't understand the essence of delegating. In my projects, I try to avoid it in every possible way. I watched various videos on this topic, read articles, but I could not understand the essence of delegation. Now I decided to devote some time to this and created a simple project to figure it out, but I still can't get it.

I want to pass text when clicking on a button from FirstViewController to SecondViewController , but this code doesn't work, what is the reason? What am I doing wrong?

protocol Protocol {
    func  fillTheLabel(with text: String)
}

class FirstViewController: UIViewController {

    var delegate: Protocol?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func buttonPressed(_ sender: Any) {
        let text = "Some Text Here"
        delegate?.fillTheLabel(with: text)
    }
}

// there is a segway between the button and the SecondViewController

class SecondViewController: UIViewController, Protocol {
    
    var firstVC: FirstViewController?

    @IBOutlet var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        firstVC?.delegate = self
    }
    
    func fillTheLabel(with text: String) {
        label.text = text
    }
}
VyacheslavB
  • 181
  • 9
  • `firstVC` is nil so SecondViewController will never be set as delegate. Also having one view controller being the delegate of another view controller is maybe not the best example of using the delegate pattern. – Joakim Danielson Jul 24 '20 at 11:22
  • Ok, first. In a SecondViewController you HAVE NO instance of FirstViewController actually (you can check if variable nil or not, by printing, or via breakpoint and "po"-command, or manually) – Ilya Muradymov Jul 24 '20 at 11:23
  • And how I can fix it in this example? Or delegates not used at all in such cases? – VyacheslavB Jul 24 '20 at 11:26
  • 1
    As Joakim told you – having one view controller being the delegate of another view controller is maybe not the best example of using the delegate pattern. But if you want – you can get instance of VC you need from Navigation Controller stack if it exists there or instantiate VC you need from storyboard – Ilya Muradymov Jul 24 '20 at 11:28
  • 1
    Delegation isn't usually used to pass data in this direction. It is commonly used in the other direction, to pass data back from VC2 to VC1. See [this answer](https://stackoverflow.com/a/27457890/1630618) for an example. – vacawama Jul 24 '20 at 11:29
  • 1
    Better is to create a class with your Protocol and fillTheLabel function. Create some public function to setText, in this function call "delegate?.fillTheLabel(with: text)" Do allocation / init of class on VC. Set your VC as delegate. And from VC call setText on instance of Class. And in the method fillTheLabel you will get info from your class. That way it will work. – Ilya Muradymov Jul 24 '20 at 11:29
  • 1
    and to be honest, info about direction is for nothing (vacawama) – Ilya Muradymov Jul 24 '20 at 11:35
  • Ilya Muradymov, why do you say that the first controller does not exist on the screen at the same time as the second? What if I use segway Show Details? I can see both controllers on the screen at this moment. – VyacheslavB Jul 24 '20 at 11:44
  • 1
    Actually I know the ways that you can set several VCs together. Even some million, with pixel on pixel area on screen, but, NORMALLY you see one VC, and actually your original question is not about this. Just it is a bad practice to set one VC as delegate of another. Few times spoken here moment. – Ilya Muradymov Jul 24 '20 at 11:48
  • I recommend you to use weak reference for delegate to avoid reference cycle with different controller. 1) Extend protocol with AnyObject: protocol SomeDelegate: AnyObject { } 2) Use: weak var delegate: Protocol? 3) Congrats, reference cycle problem is avoided! – Ildar.Z Jul 24 '20 at 12:29
  • good mention about weak reference! – Ilya Muradymov Jul 24 '20 at 14:25

1 Answers1

0

S0, as been told in comments:

– It doesn't work because your VC1 is nil in VC2

– It is bad practice to make one VC delegate of another

Simple theoretical example is:

You have class DataParser that loads some data from internet, doing parsing, making data to be treated as your models, saving it to local storage. It takes time. And your VC should present this data after all preparations done.

After job finished class DataParser should notify VC that it's done with data and VC is welcomed to show it.

Of course VC should "show" their interest, by implementing:

dataParser.delegate = self

Class is "looking for" some delegate, who is interested in his message:

delegate?.dataIsReadyToBeShown(with: data)

Delegate (VC here) gets data in

func dataIsReadyToBeShown(with data: AnyClass)
  • 1
    Delegation is in fact very simple: I delegate to someone else the task of doing something for me. But it is hard to grasp at the beginning). I wrote a basic explanation of delegation mechanism some time ago. If that can help you understand better, here is the link: https://forums.developer.apple.com/thread/111569 – claude31 Jul 24 '20 at 13:52
  • Claude. You also forgot to make a delegate property WEAK! – Ilya Muradymov Jul 25 '20 at 06:23