I'm using this library to show a side menu inside my app: https://github.com/jonkykong/SideMenu
All is fine except for one thing. When I present a viewcontroller from the side menu, and then dismiss this view controller to the main view controller, the viewWillAppear and/or viewDidAppear of the main view controller is not called ever.
From SideMenuVC (side menu view controller) I present other view controller:
let myPortfoliosNC = storyboard!.instantiateViewController(withIdentifier: "myPortfoliosNC")
present(myPortfoliosNC, animated: true, completion: nil)
Next, form the myPortfolioNC i dismiss (from the first view controller) and when go to main view controller the viewDidAppear and viewWillAppear is not called. Any idea of what i'm doing wrong ??
Related
I have a container view that is set as the input accessory view for my view controller. Whenever I present a modal view controller the input accessory view dismisses.
I tried using the code below which works when I present the modal view controller. However, that view controller presents an image picker controller and after presenting that image picker controller I get the error "Keyboard cannot present view controllers." Is there a way to keep the input accessory view open for any view controllers presented on top of the base view controller.
let rootViewController: UIViewController = (UIApplication.shared.windows.last?.rootViewController)!
rootViewController.present(addVideoController, animated: true, completion: nil)
I don't think there is a way to keep an inputAccessoryView active through the view hierarchy - either pushing the view onto a navigationController stack or displaying modally will not keep the root's inputAccessoryView visible from my experience. This is because inputAccessoryView is a member of the UIViewController class rather than the window itself - and the new UIViewController you are making active does not have an inputAccessoryView.
I believe you will need to add a inputAccessoryView into the UIViewController class that you are presenting modally. You can set it up the exact same way that you did with the root view controller's class.
// call this in your root view controller that has the inputAccessoryView currently displayed
let addViewController = YourViewControllerClass()
modalViewController.inputAccessoryView = self.inputAccessoryView
self.present(addViewController, animated: true, completion: nil))
I have a view controller as my initial view controller. there's a button in it(GO button) which when the user taps, it should go to another view controller(let's call it Destination view controller with label 'This is where i wanna go'). Meanwhile i want to pass it through a Tabbar controller. The reason is i want to have tabbar in my navigation stack.
I wish to go directly to the Destination view controller while pressing go button but it should show the tab bar items at the bottom.
So for achieving this in FirstViewController didLoadMethod I checked a bool value and pushed the view controller to the Destination view controller. I achieved the result I.e when pressing the Go button it goes to the Destination view controller and has tab bar items at it's bottom.
But the problem since it passes through the Tabbarcontroller the FirstViewController is shown for some seconds and then it pushes to the Destination view controller. I wish to hide FirstViewController while this transition takes place.
How to achieve this?
Picture shows what i want. what can I do to hide firstviewcontroller while having it in navigation stack?
I think this can be done in a simple way -
In the first viewController of the tab bar has a viewDidLoad() function or you can use loadView() which is called before the viewDidLoad() function. Push to the next viewController in the function.
Put your push navigation code in one of those functions
*You cant see the current view coltroller, it will push the screen to your required viewcontroller before loading the tab bar initial view contoller.
Hope it will work for you.
or >>>> you can check it out
let storyboard = UIStoryboard(name: "your_storyBoard_name", bundle: nil)
let viewController1 = storyboard.instantiateViewController(withIdentifier: "firstViewController")
let viewController2 = storyboard.instantiateViewController(withIdentifier: "secondViewcontroller")
let controllers = [viewController1, viewController2]
self.navigationController!.setViewControllers(self.navigationController!.viewControllers + controllers, animated: true)
The effect you're trying to produce is hard to do in a storyboard. Programmatically you would simply create the Tabbar Controller (with its children) and the "This is where I want to go" Controller, and then ask the navigation controller to show both at the same time.
For example, after "Go" is tapped, this is the code I would run inside your first view controller:
let tabBarController = UITabBarController()
let finalDestination = UIViewController()
var viewControllers = self.navigationController?.viewControllers ?? []
viewControllers.append(tabBarController)
viewControllers.append(finalDestination)
self.navigationController?.setViewControllers(viewControllers, animated: true)
Given the structure you shown, where the view controller A is the root view controller of the TabBar, you should push the second view controller B on the navigation stack inside either willAppear or didLoad of view controller A, according to your personal business logic (flag, conditions, etc.).
The trick here is to use either pushViewController or setViewControllers with animated: false so that the navigation stack will be set immediately during willAppear/didLoad and it won't show the push animation of B over A. This way, at onDidAppear the layout will be already fully rendered in it's final state: with B at the top of the navigation stack and no animations in progress.
I've got a kind of complicated modal segue setup in my project. I'm trying to dismiss a view controller another view controller previously presented. I'm doing so with this code:
if(self.presentedViewController != nil){
print(self.presentedViewController!)
self.presentedViewController!.dismiss(animated: false)
print(self.presentedViewController!)
}
The prints are there for debugging purposes. They show that the presentedViewController doesn't actually get closed.
Even though I've set animated to false, I still see an animation occuring in the app when dismiss is called. Yet, the VC doesn't actually get dismissed.
Anyone knows a solution?
Apple
The presenting view controller is responsible for dismissing the view
controller it presented. If you call this method on the presented view
controller itself, UIKit asks the presenting view controller to handle
the dismissal.
dismiss(animated:completion:) dismisses the view controller that was
presented modally by the view controller.
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss
If you present a view controller from the app's root, for example:
Presenting view controller
let root = UIApplication.shared.keyWindow!.rootViewController!
root.present(someViewController, animated: true, completion: nil)
You would dismiss it from the presented view controller like so:
Presented view controller
let root = UIApplication.shared.keyWindow?.rootViewController
root?.dismiss(animated: true, completion: nil)
I have a view controller that presents another view controller like so
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
let qrScannerViewController = QRScannerViewController()
qrScannerViewController.presentedBy = self
self.present(qrScannerViewController, animated:true, completion: nil)
// Do any additional setup after loading the view.
}
qrScannerViewController (the presented view controller) then calls
self.dismiss(animated:true, completion: nil)
which to my understanding calls the presenting view controllers dismiss function anyway.
Problem is, once the presented view controller has been dismissed, the presenting view controller's viewDidLoad gets called again, meaning the view controller is presented again.
Any ideas how to get around this?
Even if I use delegation the presenting view controller's viewDidLoad gets called again
Thanks
The presenting view controller is defined in a UITabController:
let qrPlaceholderViewController = QRPlaceholderViewController()
let controllers = [restaurantNavController,favouritesViewController, qrPlaceholderViewController, profileViewController]
self.viewControllers = controllers
Ok so the problem here was ARC doing its job.
When the presenting view controller presented the other view controller, ARC was unloading the presenting controller. This meant that when the presented view controller was dismissed, the presenting one was reinstantiated, hence forcing the viewDidLoad method to get called again
Solution:
A few solutions are available:
First of all I just stored a flag in a helper that I could check in the viewDidLoad method to see if it had already been loaded before and if it had, dont present the view controller again
Alternatively, I changed to once a qr code had been scanned, call a function in the presented view controllers delegate (the presenting controller) that navigated to the view that I wanted, therefore skipping the issue of the viewDidLoad being executed again.
let dialog: FriendCheckInDialogViewController = storyboard?.instantiateViewControllerWithIdentifier("FriendCheckInDialogViewController") as! FriendCheckInDialogViewController
dialog.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
If I use
self.navigationController?.presentViewController(dialog, animated: false, completion: nil)
Then transparency works. But popToRootViewControllerAnimated does not, so I cannot go back.
If I use
self.navigationController?.pushViewController(dialog, animated: false)
Then background becomes black instead of transparent. But popToRootViewControllerAnimated works, so I can go back.
What should I do?
You seem to be mixing different presentation styles.
If you present a view controller modally using presentViewController, then you can dismiss it using dismissViewController. In this case you can present the view controller modally over the current view controller.
If you push a view controller onto the navigation controller stack, then you can pop that view controller back off, but the pushed view controller replaces the current view controller, so you can't expose it "underneath".