viewWillAppear called again and again - ios

Apple says in the viewWillAppear Documentation
This method is called before the receiver’s view is about to be added
to a view hierarchy and before any animations are configured for
showing the view.
What does this sentence means
before any animations are configured for showing the view.
I am actually expecting the viewWillAppear to be called when the view is added in to the view hierarchy but when i come back from the background app to the foreground it also calls viewWillAppear when the view controller is already in the view hierarchy. Does it have to do some thing with the sentence
before any animations are configured for showing the view.
also the similar thing happens if i switch the tabs or some modal view controller is dismissed from my view.

The most classic and reliable method for the purpose you need is viewDidLoad.
viewWillAppear/viewWillDisappear and similar methods are designed to be called multiple times, viewDidLoad - only once, when the view first loads itself on the navigation stack, for example.

Related

SWIFT 3, Eureka: When using a navigation controller, the keyboardWillShow callback is not called

Scenario
NavigationController is a root controller of a TabBarController
TabBarController has 2 UIViewControllers
One UIViewController has a function that presents another UIViewController
UIVIewController that is presented has a StackView
Instantiates a subclass of FormController (eg: FormVC) and adds to Stack as subview
Problem
The keyboardWillShow function of FormVC does not get called. The keyboard actually adds the input to the row, but the auto scrolling does not happen
Is this only a problem in Eureka or perhaps a problem using the Navigation controller's pushViewController?
Answer
The correct way to use the FormVC is with the Container, as per the comment in the question.
Here is a great explanation credit to Miguel Revetria - source, github:
Hi chefren the problem with your approach is that the
FormViewController lifecycle is not being handled because you are not
adding it to the view controllers hierarchy. Actually you are only
adding its view to one of your views.
The function keyboardWillShow is not being called due to the
FormViewController adds this observer to the notification
Notification.Name.UIKeyboardWillShow from the function viewWillAppear,
which in your case is not being called. As this, other stuff may not
work properly, because the view controller lifecycle is not being
handled.
That is not the way the FormViewController should be used. Using it in
that way may end up with an undesired behavior like you experienced.
The correct way to embed a FormViewController in other view
controller's view is by adding it as a Child View Controller. See this
Apple guide for further information Implementing a Container View
Controller. Additionally, in storyboards you can use a Container
View.
Regards

self.navigationController is nil during state restoration

After implementing state restoration in my app I am having difficulty with my view controllers.
My issue is that in viewDidLoad of the view controller I am attempting to restore the self.naigationController property, which is nil.
I have set breakpoints in the viewDidLoad method of each view controller that comes before the one I am trying to restore. In the first view controller, the navigation controller is found. In every one after that, including the one I am trying to restore, the navigation controller is nil.
This is causing bugs where I cannot set the navigation bar visibility, views are misplaced, etc.
Does anyone have an idea why this might be?
Try moving the code to viewWillAppear.
Unlike viewDidLoad, viewWillAppear can get called multiple times, so take care to make sure your code is idempotent. That is, make sure the results are what you expect if the method is called repeatedly. For example, make sure you don't initialize a new subview if the view has already been added.
The navigationController property searches up the parentViewControllers to find one of class UINavigationController. Only view controllers loaded from the storyboard can find their navigation controller at the viewDidLoad time (and in awakeFromNib). It is likely you are instantiating a new instance of the view controller during the restore process rather than using the one that was created by the storyboard. The solution is either to help the restore process find the existing view controller if it has changed paths e.g. because of split controller orientation change (via viewControllerForRestorationPathComponents in your app delegate) although that comes with its own set of issues, or make your view controller work by not requiring the nav controller in the viewDidLoad, e.g. put it in the viewWillAppear as others have suggested.

Possible to update a UIViewController that is not on screen?

I have a side menu controller that is part of the rootViewControllerI never remove it from there and when it slides off screen - its just an animation that updates its frame details.
Is it possible to update this view, while it is not displayed on scene? I have a UiTableView in there and I would like to reload it while it is off screen - so when the user slides out the screen, its already populated with new content.
My first approach was a delegate - however, the delegate method doesn't get fired and I believe this is due to it being off screen. But, I somehow think side its in UIWindow it is never really deallocated like a normal view when it leaves the screen?
Edit
I am using this Github project for the menu.
The view I want to update is in a UINavigation controller, one level deep. I can get the current instance of it - however, the delegate method doesn't trigger.
It seems to me that you are going with something like this. Even if not, look at the example. Here RootViewController is always alive and you move one viewcontroller to parent view controller and remove other one.
I have two ways to fix it:
If you are removing first view from parent view controller. Don't remove it. So the controller is still live and use delegates to trigger the event.
Remove first view controller then use Root view controller to get the updates and once the previous view controller loads back take updates from root view controller and update this one.
Hope it can atleast give you an idea.

IOS - Disable View Cache in View Controller

I am pushing and popping from one view to the other within my App. The view is being retained in the memory so when you hit the "Back" button after pushing a view, the same screen that was before you pushed the view is retained.
For some reason, I will need to reload the parent view after popping from a child view. I need to display different content based on the actions the user taken when they were redirected to the child view.
I am using UINavigationController to navigate from one view to the other. I need it so I can easily go back and forth within the different views of the App.
The correct way to do this would be to perform your actions in viewDidAppear. Initialisation code that you write in viewDidLoad is called only once. But in viewDidAppear you can refresh your view's content every time the view is added to the window. The controller is retained in the memory for performance reasons. Removing it would hamper that factor.
Here is a stack overflow post that explains the different view* callbacks in good detail.

What's the difference between the RootViewController, AppDelegate and the View Controller classes that I may create?

I am trying to learn programming for the iPhone and I keep seeing these files and I am not sure when is each file and content of those files referred to in the execution of a program built for the iPhone. I am trying to follow tutorials and tips available online but nowhere is there a point by point comparison or something like that. It would be great if any of you could list a few basic differences like when is each file referred and what should ideally go into each file and so on. Thanks for your time already.
In general, delegates can be thought of as event handlers. Accordingly, the AppDelegate is the main event handler for your entire application. It is told when the application has launched, when it will exit, when a Push notification comes in, when the app has gone into the background, etc. One of those events - applicationDidFinishLaunching - is typically responsible for creating the application's window and adding views to that window.
In most applications, the view that is added to the window is actually controlled by a UIViewController. Each UIViewController is responsible for managing the appearance of one main view plus all of its subviews. For example, a UITableViewController is responsible for managing a UITableView (main view) and all of the UITableViewCells (subview) that are inserted into that UITableView. The UIViewController typically acts as a delegate (event handler) to the views it is responsible for. When a user taps a table view cell, a method in the UITableViewController is called. When the user swipes to delete a separate method is called.
A generic UIViewController provides the same basic functionality, but for custom views. For example, the UIViewController may be responsible for displaying a few text views and a button. The UIViewController would create its main view, the text views and the button view. The text views and button view would be added to the view controller's main view as subviews. The UIViewController would register itself as the delegate for events from the text view (for example learning when the user has finished editing the text in the text view). It would also register a method to handle a button press originating from the button it owned. When any of these registered events occur, methods on the UIViewController are called allowing you to take whatever action is needed.
The rootViewController is a specific type of view controller used with navigation controllers. If you want an application that has the typical iOS navigation view hierarchy, your AppDelegate would typically add a UINavigationController to the app's window. That UINavigationController is useless without actually having content to display. That is where the rootViewController comes into play. You are responsible for providing a view controller (such as the one described above) to act as the first view stored in the UINavigationController's stack of views. This view will be displayed when the app starts up and anytime that the user pops subsequent ViewControllers off of the UINavigationController's stack.
Long winded I realize - but hope it helps.

Resources