-3

Refernce image Im new to protocols, I tried the following implementation to achieve the protocols, but im getting nil value for the protocol object

import UIKit

//MARK: step 1 Add Protocol here.
protocol MyDelegate: class {
   func changeBackgroundColor(_ color: UIColor?)
}

class ViewController: UIViewController {
//MARK: step 2 Create a delegate property here.
    weak var delegate: MyDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    //MARK: step 3 Add the delegate method call here.

      delegate?.changeBackgroundColor(UIColor.red)
   }
}

Here I am getting delegate value nil and protocol not getting called.

here is the implementation import UIKit

class HomeViewController: UIViewController, MyDelegate {

func changeBackgroundColor1(_ color: UIColor?) {
    self.view.backgroundColor = color
}

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.

    callVC()


}
func callVC() {

    let vc = ViewController()
    vc.delegate = self

}
func changeBackgroundColor(_ color: UIColor?) {
    self.view.backgroundColor = color
}

5 Answers5

3

In short:

You have forgotten to set the delegate to the object that conforms the protocol.

Detailed Answer:

Protocol is an agreement between two objects so that you know a delegate will have some specified functions ready to be called. Let's explain with an example:

Suppose that you have two view controllers called A and B. You have defined your protocol in global (as you did in your code). Then you create a property called delegate in A which will hold a weak reference of any object conforms the protocol. In this case, this held object reference is B.

So you need to have a property in A like below:

weak var delegate: MyDelegate?

Then determine this delegate to be the reference of what you need. In our example, it's B. So you need to set it in B as below.

// Somewhere you have the reference of the object or where you initialize it.
instanceOfA.delegate = self

Finally you conform the protocol in B like:

extension B: MyProtocol {
    func changeBackgroundColor(_ color: UIColor?) {
        // some implementation goes here
    }
}

There you are. Now, you can make sure that you have delegate object and protocol methods are getting called if you have completed steps above correctly.

Yusuf Kamil AK
  • 771
  • 8
  • 17
0

The problem lies in your callVC method:

func callVC() 
{
    let vc = ViewController()
    vc.delegate = self
}

You create an instance of your ViewController, but you are not doing anything with it. No methods, aside from initializer, will be called on that view controller because it's not a part of active navigation stack. Also, since it's just a local variable (not retained anywhere) it will be deallocated immediately after leaving the method scope.

What you need to do is to present the view controller somehow - either with a navigation controller, or as a child to the current view controller

func callVC() 
{
    let vc = ViewController()
    vc.delegate = self

    addChildViewController(vc)
    view.addSubview(vc.view)
    vc.didMove(toParentViewController: self)
}

or if you're using navigation controller

func callVC() 
{
    let vc = ViewController()
    vc.delegate = self

    navigationController?.pushViewController(vc, animated: true)
}
mag_zbc
  • 6,801
  • 14
  • 40
  • 62
0

Hi Smart i think the problem is when you set the delegate

override func viewDidLoad() {
super.viewDidLoad()

    // Do any additional setup after loading the view.

    callVC()


}
func callVC() {

    let vc = ViewController()
    vc.delegate = self

}

Because you set the delegate for the class ViewController, but you don't present the viewController at all; you should set the delegate before presenting the ViewController, one way to do it is to present the ViewController and in function callVc add this

func callVC() {

    let vc = ViewController()
    vc.delegate = self

    //Present the viewController with this
    present(vc, animated: true, completion: nil)

}
-1

Your optional delegate variable is nil. You need to set it first from the UIViewController you are segueing from. For example.

class OtherViewController: UIViewController {

   override func viewDidLoad() {
       super.viewDidLoad()
       self.performSegue(withIdentifier: "addHereTheSegueIdFromStoryBoard", sender: nil)
    }

   override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

       if segue.identifier == "addHereTheSegueIdFromStoryBoard" {
           guard let vc = segue.destination as? ViewController else {return}
           vc.delegate = self
       }
    }

}
Kegham K.
  • 1,589
  • 22
  • 40
-1
import UIKit

class ViewController: UIViewController {

    weak var delegate: MyDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()

     if delegate != nil {
      delegate?.changeBackgroundColor(UIColor.red)
     }
   }
}

Call like

class SecondViewController: UIViewController(), MyDelegate {

func callVC() {

let vc = ViewController()
vc.delegate = self

}

func changeBackgroundColor(_ color: UIColor?) {
//Code here
}

}
Kathiresan Murugan
  • 2,783
  • 3
  • 23
  • 44