I'm using the Facebook iOS SDK to have users authenticate and when they log out and log back in, the state of the main view controller, the one with the logout button, is in the same state as when they left it.
How can I completely remove the view controller from memory so that every time they log back in, the view controller's viewDidLoad method is called and the view controller is re-initialized.
When done with it each time you need to release all references.
When you need to show it again, create and use a new instance. This is the only way to ensure viewDidLoad is called each time you need it.
Or if you want to keep reusing the same one over and over, add a restart method (or something similar). The implementation of this method can reset the UI to whatever starting state you need. Or you can put this logic in the viewWillAppear: method. This depends on whether viewWillAppear: can be called due to pushing and popping other view controllers.
Related
I wonder if dealloc is always called when you close a ViewController in Objective-C for iOS. I've done some tests and it seems like it. Except I don't get any logs when I swipe close the application. I figured that maybe XCode doesn't log things if you fully close the app like that.
The reason I wonder this is because I'm sending analytic data when one of the ViewControllers closes and I kinda need to know if dealloc is always called or if there's any better way doing this.
If you want to get notified when app is killed via Swiping , you can use applicationWillTerminate method and in this method , you can check for current view controller in navigation stack and send analytical data for that View controller .
It's not defined when dealloc will be called for a view controller (or pretty much any class), therefore don't use it for sending analytics.
Use viewDidDisappear instead, which you can rely on to be called when the view controller has been removed.
I'm looking into the viewDidLoad and viewDidAppear methods to better understand what they both do and I came across an article which uses the example of a banking application to explain how these methods work:
Consider a banking application that shows your current balance. A user
can tap on a button, which presents a list of nearby ATMs in a modal
view controller. In order to get the list of nearby ATMs, the
application must make a core location and web service request.
In this situation, a programmer could get away with requesting the
list of nearby ATMs from the server in viewDidLoad. The view
controller is only presented once, both viewDidLoad and
viewWillAppear: will be called back to back and only once for that
particular view controller instance. The net effect of the code in
either of these two methods will be the same.
But this is a bad idea. Consider what would happen if you wanted to
move the ATM view controller into a tab bar controller. Now, the ATM
view controller – with its ATM fetching code in viewDidLoad only
fetches the list of ATMs once. So you are in Atlanta on Tuesday, open
up your application to look for an ATM, then check your balance. Then
you travel to New York on Wednesday, re-open the banking application,
and you only see ATMs in Atlanta. The view was already loaded, no need
to call viewDidLoad and now you’re looking at stale data.
Sadly, I still don't fully understand how/why both viewDidLoad and viewWillAppear will be called 'back to back', or what adding the ATM view controller to a tab bar controller means in terms of these methods.
viewDidLoad method will call only once a life time of viewController and that is when viewController object will first load in memory.
where as viewWillAppear method will call every time when a view will appear to screen or you can say will be topViewController...
Explanation:
Consider you have tab based app with two tabs. Tab1 associated with viewController1 and tab2 is associated with viewController2. Now when you will run your app and you will see tab one is selected and viewController1 is on view and you want to change to tab2, when you will tap on tab2 then tabVieController2's object will create and load to memory first time hence its viewDidLoad method will call, and soon after that it will appear to window and viewWillAppear will also get call.
Now if you you try changing tabs by click on them only viewWillAppear methods will get called for both, as they are in memory already.
It simple, viewDidLoad get called when the view is load in, either via NIB, storyboard or with the loadView method. The viewWillAppear: is called when the view is presented.
When a view is added to a tab bar it only gets load once, thus the viewDidLoad will only be called once. But if the user switch to an other tab and back to the same view the viewDidLoad will not be called. This is because the view is already loaded.
However the viewWillAppear: is called in both cases just before the view is shown. Thus this will be called when the user first opens the tab and when it switches back to that tab.
I think they are referring to the fact that the view is loaded every time the modal view controller appears (thus the data is constantly refreshed) but only once when it is part of tab bar (only loaded on app launch). Kind of a whacky example to explain the methods though.
You might want to read up on the view controller lifecycle to know when to implement what in which method:
Responding to Display-Related Notifications
View Loading and Unloading
For instance, if I press 'back' on the navigation bar to go back to the first viewcontroller, then the variables don't get reset - they stay at whatever value they got to before I pressed back. So then if I go back to the second viewcontroller again, it doesn't completely restart everything.
I could just programmatically reset everything in viewDidLoad everytime, but I'm wondering if there is a simple method or something already made for this.
It's all done in storyboards so I don't have code to show.
I could just programmatically reset everything in viewDidLoad everytime
Actually, this wouldn't work. viewDidLoad is only called once per instance.
You probably don't want to do this, since most users will be confused and annoyed by the behavior. But if you're sure you want to, you could:
Reset everything in viewWillAppear:, which will get called every time, although this will also get called if the user leaves and then re-enters your app
Use the back button's behavior to trigger a method call that will reset the variables to whatever you want. For example, you could do this in prepareForSegue: using the delegation or notification patterns, depending on what's appropriate in your app.
I'm wondering if there is a simple method or something already made for this.
It shouldn't be that hard, but there's no built-in "reset view" behavior, since this is almost always considered undesirable.
Use -viewWillAppear:, -viewDidAppear:, -viewDidDisappear, and/or -viewWillDisappear:.
I'm subclassing UINavigationController and want to in order to add the ability to add previously popped view controllers back onto the stack, akin to a forward button in a web browser.
When the user presses a button, I want to add the most recently popped off view controller back onto the stack. I do this by getting the view controller at the top of my custom stack, and calling pushViewController:animated: with it.
In the case where taps on a table view cell or something to go forward a new way into the view hierarchy, I want to clear my "popped view controllers" stack. Similar to how if the user clicks on a new link in a web browser the "forward" history is cleared.
This is where my issue lies. I don't know how to differentiate between when I call pushViewController:animated: in order to restore a view controller, and when the user taps a cell to push one. In the latter case, I want to clear my stack, but in the former I don't want to.
I can't figure out what to do here. In a perfect world pushViewController:animated: would have userOptions: parameter or something on it that would allow me to distinguish between how it's being used, but unfortunately that parameter doesn't exist.
Such an issue must come up rather frequently. How would I deal with it in this case? How would I differentiate between the circumstances in which the method is being called?
If I follow you correctly one common approach to doing this is:
Your "goForward" method should call your superclass' pushViewController:animated:
Override pushViewController:animated: to call both your superclass' pushViewController:animated: and your "clearStack" method.
It seems to me that you need two different methods in your subclass. One for the case where you want to restore a view controller, and one where you want to clear the stack. Both will perform some custom logic and call pushViewController:animated: on super.
I would like to move back to my main view using a segue. When the home button is pressed and the app enters the background.... then later the user wishes to open the application again bringing it to the foreground I would like a segue to be run which takes them from whatever view they were in back to the 'main view'. I dont mind using multiple segues... or how could I access these segues in the app delegate for example.
What is the best method for this? Thankyou! beer and points for everyone who gives a good answer ;).
You may implement the applicationWillEnterForeground:application: method (from the UIApplicationDelegate protocol). This method is called whenever your application's state changes from backgo to inactive state (before it goes to active).
In this method you could call performSegueWithIdentifier:identifier sender:. If you have a segue from each possible view back to your main view, your are done.
However, unless your application has a very complex state that would need lots of time to reconstruct, I would recommend to do general a re-initialization of your application in application:didFinishLaunchingWithOptions: or applicationDidBecomeActive:. In this way it is easier to preserve a consistent state.