Pop to next viewController in ios - ios

I used this code :
self.navigationController?.popToViewController(vc, animated: true)
By using this it is poping to view controller but tableView is not loading at a time,i need to go back and come again then it is loading.
This code :
let vc = self.storyboard?.instantiateViewController(withIdentifier: "DiscountViewController") as! DiscountViewController
self.navigationController?.pushViewController(vc , animated: true)
By using this code i'm popping to view controller ,also loading tableView at a time, but the problem is, that it is going two or three to return back because we are pushing the viewController.
How can solve this by using popToViewController(vc, animated: true) and load tableView at a time?
Initially this code
self.navigationController?.popToViewController(vc, animated: true)
has worked. Whatever I'm trying also I'm not able to pop view controller and reload() tableView when popViewController is used.
How to solve this?

If you are popping back to a previously displayed view controller, then you can reload your tableView by doing reloadData in that DiscountViewController's viewWillAppear function.

Related

Presenting a new view controller and then dismissing it, calls init() on the parent view controller

I am finding a very weird behaviour on my app, the structure of the view controllers is the following:
TabBarViewController contains:
- NavigationController(root is HomeViewController)
- NavigationController(root is SearchViewController)
- NavigationController(root is ProfileViewController)
When I am in HomeViewController, I present modally PremiumViewController
#objc func premiumTapped() {
let premiumViewController = PremiumViewController(viewModel: PremiumViewModel(networkService: NetworkService(), purchasesService: PurchasesService.shared))
navigationController?.present(premiumViewController, animated: true, completion: nil)
}
All fine until here.
Now I dismiss PremiumViewController.
dismiss(animated: true, completion: nil)
What happens is that HomeViewController calles it's init() and viewDidLoad()!
How is this possible? HomeViewController has been existing all this time, so why it calls init again?
Thanks to #rmaddy I found the issue.
To find it out, I put a breakpoint in the init() function that was called all the time. I found out that who was calling it was viewWillAppear() from the TabbarViewController.
The issue was that I initialise the tabbar view controller on the viewWillAppear() rather than on viewDidLoad(), which made recreate all the tab controllers every time one of the views appeared.

back to initial view controller

As you can see i have an initial view controller with label in it "Initial ViewController". In this view controller i use below code to go to selected tab of Tab Bar Controller
let vc1 = sb.instantiateViewController(withIdentifier: "tabbar") as! UITabBarController
vc1.selectedIndex = selected
let controllers = [vc1]
navigationController!.setViewControllers(controllers, animated: true)
In my First View, there's a button "Present VC" which presents "Presented View".
let vc1 = sb.instantiateViewController(withIdentifier: "PresentedVC") as! PresentedVC
present(vc1, animated: true, completion: nil)
Now i want to go back from presented vc to root vc(Initial View Controller). I can do this with:
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "FirstNavigationController") as! FirstNavigationController
UIApplication.shared.keyWindow?.rootViewController = viewController
but this instantiate Initial View Controller every time and views remain in memory. How can i go back to Initial View Controller without instantiating it?
PS: FirstNavigationController is initial Navigation Controller.
At the very beginning you remove the initial view controller by doing this:
navigationController!.setViewControllers(controllers, animated: true)
All the previous viewControllers are gone now and replaced with the tabbar controller and its children.
If you want to go back to the initial controller, you will have to push the tabbar onto the stack instead of replacing everything with it. E.g.
navigationController?.pushViewController(tabbarVc, animated: true)
First when you did this
navigationController!.setViewControllers(controllers, animated: true)
the initial VC is deallocated (if it has not a strong references)
to keep it you can use push , pop instead of setViewControllers but note it may cause memory issues if you have heavy processing in your app as it will remain in navigationController stack
You are missing the concept between "Presenting" or "Setting" View Controller & "Navigating" the View Controller. You will get the answer, once you understood the concept. Here, it is..
When you are setting the ViewController, you are completely replacing the stack container to the new view controller. the way you did it here:
navigationController!.setViewControllers(controllers, animated: true)
In this case, STACK holds the addresses of the latest set/presented ViewControllers that means previous whole ViewController vanished.
On the other hand, if you are navigating to other view controller by pushing it. you can go back to previous controller by simple popping the ViewController address from stack. or to next ViewController by pushing
e.g:
self.navigationController?.pushViewController(tabbarVc, animated: true)
self.navigationController?.popViewController(animated: true)
Summary:
If you push TabBarController then, only you will get InitialVC.
Now, in your case, you are setting the ViewController and hence, you are not getting InivtialVC. Try Pushing tabbarVC This will work.
navigationController?.pushViewController(tabbarVc, animated: true)

Load data with Core Data in UICollectionView before animation

I am pretty new to iOS development, but I could not find an answer to this question (maybe I could not find the right keywords to search..?).
Anyway, I have this "problem":
I have 2 storyboards, A and B, both with some views inside.
I go from view A-2 to view B-1 via #IBAction - a simple button click - with the following code:
#IBAction func onExercisesButtonTapped(_ sender: AnyObject) {
let storyboard = UIStoryboard(name: "Exercises", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "ExercisesVC") as UIViewController
controller.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
present(controller, animated: true, completion: nil)
}
On the other hand, in the B-1 view I have a UICollectionView that is populated with data coming from a CoreData model.
The cells within the UICollectionView appear only after the animation is completed. If I set animated: false in the perform function and thus no animation is performed from A-2 view to B-1 view the cells are immediately visible.
The cells are the only element that appear after the completion of the animation. What is the cause of this behaviour? Can I avoid it with some sort of preloading/prefetching or other methods?
Is there a way to display the cells before the animation starts, just like the UICollectionView background and all the other elements within the view?
Thank you in advance :)
Update your view in viewWillAppear:.

Using viewDidAppear to present a View Controller, re-opening it when it's closed

In my App, I've created a new storyboard that serves as a very basic tutorial for how to use certain features. (Instructions.storyboard). This storyboard has it's own class - InstructionsVC.swift
I want to present InstructionsVC when MainVC loads within viewDidAppear.
It works great. Fires up on App load just like it's supposed to. The problem occurs when I press the [Close] button on the Instructions interface. It closes the VC, fades to the main screen, and then immediately fires the Instructions VC back up.
How can I prevent the Instructions VC from loading back up once it's closed?
func openInstructions() {
let storyboard = UIStoryboard(name: "Instructions", bundle: nil)
let instructionsView = storyboard.instantiateViewController(withIdentifier: "instructionsStoryboardID")
instructionsView.modalPresentationStyle = .fullScreen
instructionsView.modalTransitionStyle = .crossDissolve
self.present(instructionsView, animated: true, completion:nil)
}
override func viewDidAppear(_ animated: Bool) {
openInstructions()
}
And within my instructions class, I have the following action on the close button:
#IBAction func closeButtonPressed(_ sender: UIButton) {
let presentingViewController: UIViewController! = self.presentingViewController
presentingViewController.dismiss(animated: true, completion: nil)
}
Note - I'd rather not use UserDefaults to resolve this, because I'm going to be incorporating something similar in other parts of the App and don't want to resort to UserDefaults to achieve the desirable behavior.
Thanks in advance buddies!
viewWillAppear and viewDidAppear are called every time a view controller's content view becomes visible. That includes the first time it's rendered and when it's shown again after being covered by a modal or by another view controller being pushed on top of it in a navigation stack.
viewDidLoad is only called once when a view controller's content view has been loaded, but before it is displayed. Thus when viewDidLoad is called it may be too soon to invoke your second view controller.
You might want to add an instance variable hasBeenDisplayed to your view controller. In viewDidAppear, check hasBeenDisplayed. If it's false, display your second view controller and set hasBeenDisplayed to true.

Push To view controller from View is not working in swift

I tried to push to a view controller from a view class using tap gesture action. All the below lines are executed, but the control not pushing to respective view controller. I need to push to that view controller, but not to set the controller as root view,because i need to navigate back to some other navigated view controller. Any one please help me.
let webViewController = R2WebViewViewController()
currentWindow.rootViewController?.navigationController?.pushViewController(webViewController, animated: true)
try this
(currentWindow?.rootViewController as! UINavigationController).pushViewController(webViewController, animated: true)
Your root must be navVC
currentWindow.rootViewController?.navigationController?
Your problem is that your rootViewController is probably an UINavigationController already, so you should do:
let webViewController = R2WebViewViewController()
(currentWindow.rootViewController as? UINavigationController).pushViewController(webViewController, animated: true)

Resources