Byte Byte - 3 months ago 18
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

self.delegate?.myWearablesViewControllerDidFinishedChangingTracker(self)


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

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)