1

I am registering for Notifications in ViewDidLoad() in my Xamarin project. However I don't see any method where I can "Remove" the Observer. I need to execute something even when the View is not visible, so I can't give it in ViewWillAppear. Is there anything similar to "deinit" method.

Tried out "dispose" method in C#, but it didn't get called.

Even after doing a "PopViewController" the observer is still not getting unregistered. Not sure why it is not getting released from the memory even when the view controller is removed.

subin272
  • 733
  • 6
  • 24

2 Answers2

0

You can do all subscription for events in ViewDidLoad and unsubscribing them would happen automatically from IOs. If you really feel to unsubscribe them, then do it in Dispose method.

Here's an example,

In the ViewController,

// Subscribing
public override void ViewDidLoad()
{
    _homeView.HomeButton.TouchUpInside += OnHomeButtonClicked;
}

// Unsubscribing
protected override void Dispose(bool disposing)
{
    _secondView.SecondButton.TouchUpInside -= OnSecondButtonClicked;
    base.Dispose(disposing);
}
Rizan Zaky
  • 4,230
  • 3
  • 25
  • 39
  • 2
    `ViewDidUnload` has been deprecated since iOS 6 – Nick Peppers Jun 20 '18 at 13:59
  • Yeah, and even then `ViewDidUnload` only got called when the device was running out of memory and needed to free some up – Nick Peppers Jun 20 '18 at 14:30
  • After @Nick ’s comment, I did some extensive research and figured out that in IOs 6+ this method is never called for the way views are handled under low-memory. And it’s really unnecessary to unsubscribe from listeners in the viewController either. If it’s really needed to be done, then it should be done in DidReceiveMemoryWarning overridden method. I have updated the answer accordingly! – Rizan Zaky Jun 20 '18 at 14:40
  • `DidReceiveMemoryWarning` is not the place to do it either especially on newer hardware the amount of available memory may never become low enough for that method to get invoked. – Nick Peppers Jun 20 '18 at 14:56
  • I see Dispose is the place to unsubscribe listeners. And above all unsubscribing is not quite a necessity, IOs would take care of it automatically – Rizan Zaky Jun 20 '18 at 15:24
0

Depending on your needs you could override ViewWillAppear and/or ViewDidDisappear to add/remove it there.

public override void ViewWillAppear(bool animated)
{
    base.ViewWillAppear(animated);
    // subscribe
}

public override void ViewDidDisappear(bool animated)
{
    base.ViewDidDisappear(animated);
    // unsubscribe
}

Keep in mind ViewDidDisappear will be called when a new controller is pushed on top of your current controller and ViewWillAppear will get called again when that new controller is popped, which might not be suitable for whatever you're trying to do.

Nick Peppers
  • 3,161
  • 23
  • 27
  • Exactly that is not suitable for what I am trying to achieve. In my case I have to do some operations regardless of when the view is visible or not. That is why I am registering it in ViewDidLoad. – subin272 Jun 20 '18 at 14:21
  • At what point are you wanting to remove your observer, when the controller is no longer on the stack? You could also override `Dispose` and do it there or in a finalizer for your controller. – Nick Peppers Jun 20 '18 at 14:28
  • yes when the controller is not on the navigation stack. Tried with "dispose" method in C# but it didn't work. Any idea how to use that method ? – subin272 Jun 20 '18 at 14:37
  • [Here's](https://stackoverflow.com/questions/6967108/is-idisposable-dispose-called-automatically) a good example of how to use it. It's worth mentioning though even after you popped your controller it can still stick around in memory for a while before the garbage collector gets around to it. – Nick Peppers Jun 20 '18 at 14:54
  • Tried the solution (dispose pattern for a derived class that overrides Object.Finalize) given in the following link. Nothing is getting called when I pop the view controller. I have put Console logs to verify the same. Not sure if I'm doing something wrong here. https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose – subin272 Jun 21 '18 at 19:44
  • It's possible it may be causing a memory leak so it's never getting disposed when gc runs. If you're popping from the same viewcontroller maybe you can add a local bool to check in ViewWillDisappear that you only set to true before popping so it only unsubscribes when popping and not when a new controllers is pushed on top. – Nick Peppers Jun 22 '18 at 02:02
  • I might do a "popToRoot" also from a different view controller. Is there any other way to deregister notification observer ? I guess the "deinit" is doing a similar thing in Swift, but not sure about C#. – subin272 Jun 22 '18 at 03:16
  • https://stackoverflow.com/questions/21915249/how-to-detect-if-view-controller-is-being-popped-of-from-the-navigation-controll with that you might be able to also add a case to detect when poptoroot is called to still use ViewWillDisappear – Nick Peppers Jun 22 '18 at 03:40