Nsnotificationcenter calls several times the page - Swift

Asked

Viewed 90 times

1

Here’s what I wanna do:

1st user is in the app and decides to quit. By pressing the home button of the iphone.

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

Here’s what I did:

in the viewDidLoad method put

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

and in the method put

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

and put this code on all Viewcontrollers, the problem is that when I call many Viewcontroller, and then left the app and come back in the app makes as many calls from the main page as Viewcontrollers had called before leaving the app

1 answer

2


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

A 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 the same).

Don’t forget to remove objects from NSNotificationCenter, either in the deinit or in the willMoveToParentViewController(nil), otherwise the object will be retained in memory.

One second solution is to use the methods applicationWillResignActive: and applicationWillEnterForeground: of Appdelegate, which were created precisely to deal with situations of this kind.

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

You get access to your view controllers through the variable window. 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 totally against the object-oriented design standards and you will have to force downcast, in order to access the methods of your view controllers, in that way:

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

It will work, but the code will be attached, inelegant and will take a little work if you want to change the type of view controller. It’s your responsibility to decide whether this is bad for your application or not.

I saw that you are using a UINavigationController, right?

One 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 the NSNotificationCenterto receive the notifications you want to use. To give you 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 that, just go on storyboard (if you are using it) and change the class of the UINavigationController for your new class. If you are doing programmatically, just change the class that is instantiated.

Tip: I saw that, in your implementation, you simply "Pusha" (act of doing push) the mapViewControllerObject in the pile of view controllers of navigation controller. This is very problematic, for one of these two reasons: If it is the same object, it will give error, because we are not allowed to put the same view controller more than once in the stack. If it is another object, will give you headache with Leak memory, if Apple accepts the app.

Each time the user leaves the application and comes back, a new hierarchy of controllers is added on top of the old, on the same stack. Want to test? It makes this method run multiple times and keeps looking at the memory consumption in the debug of the Xcode. It may sound silly, but trust me, it’s not. As your application becomes more complex, it will become a ram-eating monster (like google and firefox), especially for those users who keep switching from app to app all the time.

One solution: reset the entire stack by calling the method popToRootViewControllerAnimated:. If you implement the third solution, this would be a good implementation for the method that is called when the notification of application Did enter foreground.

  • How can I even use that second option you gave me?

  • I improved the answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.