简体   繁体   中英

swift delegate function is not called

I know the same question is asked many times. I read most of the answers from stack overflow and tried. But it did not help my problem.

I have two view controllers

protocol UpdateDataDelegate {
    func loadData()
}

viewcontroller2 {
var delegate: UpdateDataDelegate?

override func viewDidLoad() {
        super.viewDidLoad()

}

fun saveData() {
   self.delegate?.loadData()
}
}

viewcontroller1 : UpdateDataDelegate {

var vc2 = viewcontroller2()

override func viewDidLoad() {
        super.viewDidLoad()

vc2.delegate = self

}

func loadData() {

}

}

But function loadData() from viewcontroller1 is not called.

Since I don't have the complete code before me I can only assume that the delegate is not assumed properly.

If the delegate is not initialised properly it cannot pass value to the other viewController.

You can check delegate is properly initialised by:

if let delegate = delegate{
     //Do your works here
}else{
   print("The delegate is nil")
 }

if the delegate is nil is printed in console, then the problem might be in the way the delegate was initialised

This might be because you are setting the delegate and opening an another instance of the viewController which was not assigned the delegate value.

In the code you provided I see that you are setting the delegate as

var vc2 = viewcontroller2()
vc2.delegate = self

But I cannot see the code that you used to move to the viewController2. Now we have to present this assigned viewController. Instead of using segue to move to the viewcontroller2 present this vc using the code below

 present(vc2, animated: true, completion: nil)

You should place this according to your code logic.(where your segue is triggered)

Situation 2:

If you are using segue to move to the viewController2 then the delegate should be assigned in the prepareforSegue method as below

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
      if let vc2 = segue.destination as? ViewController2{
          vc2.delegate = self
      }
  }

let me know how it goes.

A simple playground for what you are trying to do, even if I have not clear what you are trying to achieve:

import UIKit

protocol UpdateDataDelegate: class {
    func loadData()
}

class ViewController2: UIViewController {
    weak var delegate: UpdateDataDelegate?

    func saveData() {
        self.delegate?.loadData()
    }
}

class ViewController1: UIViewController {

}

extension ViewController1: UpdateDataDelegate {

    func loadData() {
        print("loadData called")
    }
}

let viewController1 = ViewController1()
let viewController2 = ViewController2()
viewController2.delegate = viewController1
viewController2.saveData()

Few notes:

  • classes should be upper case. So, ViewController1 instead viewcontroller1
  • delegates should be weak otherwise you create reference cycles
  • class should be used for UpdateDataDelegate protocol otherwise compiler will complain since weak cannot be applied to class and class-bound protocol types
  • prefer extension to conform to protocols. It makes the code easy to read

The only thing I see missing in your code is call to saveData() of ViewController2 that will in turn call loadData() of ViewController1 .

So just add:

override func viewDidLoad()
{
    super.viewDidLoad()
    vc2.delegate = self
    vc2.saveData() //Add this line to your code
}

You are good to go now :)

Edit:

protocol UpdateDataDelegate
{
    func loadData()
}
class ViewController2: UIViewController
{
    var delegate: UpdateDataDelegate?

    func saveData()
    {
        self.delegate?.loadData()
    }
}
class ViewController1: UIViewController, UpdateDataDelegate
{
    var vc2 = ViewController2()

    override func viewDidLoad()
    {
        super.viewDidLoad()
        vc2.delegate = self
        vc2.saveData()
    }

    func loadData()
    {
        print("Done")
    }
}

I have used the above code and it is working fine for me. How are you executing it? I have used storyboard and used ViewController1 as the Initial View Controller .

I assume that you need to load data when your delegate has been set up. In this case you can use magic didSet:

weak var delegate: UpdateDataDelegate? {
    didSet {
        self.saveData()
    }
}

So right after setting the delegate the needed method will be called.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM