NSNotificationCenter calls the page several times - Swift

1

I want to do the following:

1st the user is in the app and decides to quit. Clicking on the iphone home button.

2nd the user enters the app and instead of continuing on the page where it was when it left, the app automatically sends the user to the homepage.

What I did was the following:

In the viewDidLoad method I put

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(willEnterForeground), name: UIApplicationWillEnterForegroundNotification, object: nil)

and in the method I put

let mapViewControllerObejct = self.storyboard?.instantiateViewControllerWithIdentifier("MainMenuIdentifier") as? MainMenu
    self.navigationController?.pushViewController(mapViewControllerObejct!, animated: true)

>     
asked by anonymous 20.06.2016 / 15:16

1 answer

2

The problem is just putting this code in all view controllers . All of them will receive notification when the said event occurs (even if they are not the "present on the screen" at the time of the action).

  One possible first solution is to put this code only in the first view controller ( rootViewController ) of UINavigationController , since it probably never goes out of memory (unless you replace it ).

Do not forget to remove objects from NSNotificationCenter , either deinit or willMoveToParentViewController(nil) , otherwise the object will be held in memory.

  

A second solution is to use the applicationWillResignActive: and applicationWillEnterForeground: methods of AppDelegate, which were created exactly to deal with situations of this type.

To implement this option, it goes in AppDelegate and implements the logic within these two methods, being applicationWillResignActive: for when the app goes into the background and applicationWillEnterForeground: for when the app goes back to foreground. The system calls these methods automagically (with forgiveness of the joke) when the respective events happen.

You can access your view controllers via the window variable. The first view controller of the hierarchy is available in self.window.rootViewController .

The problem with this solution is that you will have to go completely against object-oriented design patterns and you will have to force downcast in order to access the methods of your view controllers in this way :

let myVc = self.window!.rootViewController as! MyViewController

It will work, however the code will get coupled, inelegant and will give a little work if you want to change the type of view controller . It is your responsibility to decide whether or not this is bad for your application.

I saw that you're using UINavigationController , right?

  

A third solution (the best and most elegant, in my humble opinion) would be to create a subclass of UINavigationController and overwrite the constructor.

In the new constructor, the only addition would be to register the object itself in NSNotificationCenter to receive the notifications you want to use. For you to have an idea, it would be something like this:

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    NSNotificationCenter.defaultCenter.addObserver(self, selector: #selector(willEnterForeground), name: UIApplicationWillEnterForegroundNotification, object: nil)
}

// implementar willEnterForeground e afins

After you do this, just go to the storyboard (if you are using it) and change the UINavigationController class to your new class. If you are doing it programmatically, just change the class that is being instantiated.

Tip : I saw that in your implementation, you simply "pusha" (push ) the mapViewControllerObject in the stack of view controllers of the navigation controller . This is very problematic for one of two reasons: If it is the same object, it is going to be an error because we are not allowed to put the view controller more than once on the stack. If it's another object, it'll give you a headache with leak from memory, so if Apple accepts the app.

Each time the user leaves the application and back, a new hierarchy of controllers is added on top of the old one, on the same stack. Want to test? It makes this method run several times and looks at memory consumption in the debug tab of Xcode. It may sound silly, but trust me, it's not. As your application gets more complex, it will become a memory monster eater (like google chrome and firefox), especially for those users who switch from app to app all the time.

One solution: Resets the entire stack by calling the popToRootViewControllerAnimated: . If you implement the third solution, this would be a good implementation for the method that is called when application did / p>     

20.06.2016 / 22:45