Byte Byte - 1 year ago 53
iOS Question

Trying to understand delegates

I have a class named 'MyWearablesViewController' in which I have writen a protocol as

protocol MyWearablesViewControllerDelegate {
func myWearablesViewControllerDidFinishedChangingTracker(viewController: UIViewController)

I have created a global variables as

var delegate: MyWearablesViewControllerDelegate?

and I have used this method several times in 'MyWearablesViewController' like


Now I want this to trigger a method in my other class named 'HomeViewController' the class is declared as

class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource,MyWearablesViewControllerDelegate

in my ViewWillAppear I have written this code

let myViewControllrer = MyWearablesViewController()
myViewControllrer.delegate = self

and implemented its function as

func myWearablesViewControllerDidFinishedChangingTracker(viewController: UIViewController) {
// some code

But my delegate is not being called. Please guide me what am I missing ?

Edit: 'HomeViewController' is in a TabBarController which contains another ViewController named 'MoreViewController' which is basically a tableView. 'MyWearablesViewController' is pushed when user tap on a cell in 'MoreViewController'

Answer Source

Okay, good news and bad news...

The good news is that you that your understanding of the delegate is absolutely correct! But the bad news is that you misunderstood a more basic concept.

You said that in viewDidAppear, you have this code:

let myViewControllrer = MyWearablesViewController()
myViewControllrer.delegate = self

You created a new instance of MyWearablesViewController, and you assigned self to the delegate variable. So far so good.

However, in tableView(_:didSelectRowAtIndexPath:) method, you did this:

let myViewController = MyWearablesViewController()
navigationController?.pushViewController(myViewController, animated: true)

You created another instance of MyWearablesViewController! And this instance is not the instance you created in the viewDidAppear method! As a result, this new instance is independent of the other instance you created earlier. And its delegate property actually is nil.

So, how can you fix it?

According to your comment on NDoc's answer, you want the delegate to be set to the HomeViewController instance.

To access the HomeViewController instance, you must first get the tab bar controller, and use the viewControllers property.

// in the didSelectRowAtIndexPath method
let tabBarController = self.parentViewController!.parentViewController! as! UITabBarController
let homeVC = (tabBarController.viewControllers![0] as! UINavigationController).topViewController as! HomeViewController

Note that I assume your HomeViewController is embedded in a navigation controller. If not, use this instead:

let homeVC = tabBarController.viewControllers![0] as! HomeViewController

And finally, you can set the delegate:

// in the didSelectRowAtIndexPath method
let myViewController = MyWearablesViewController()
myViewController.delegate = homeVC
navigationController?.pushViewController(myViewController, animated: true)