I'm presenting a Navigation Controller as a popover. First time a do it I can push to another View Controller with any issue. But, second time a present another controller the same way I can't perform a push because the self.navigationController of the presented Controller is nil. This is the piece of code I'm using to present the Controller
func instantiateEditController(view : UIView) -> UINavigationController
{
let popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("Edit Controller") as MCMEditController
popoverContent.preferredContentSize = CGSizeMake(320, 480)
let navController = MCMBaseNavigationController(rootViewController: popoverContent)
navController.modalPresentationStyle = UIModalPresentationStyle.Popover
navController.navigationBar.tintColor = UIColor.whiteColor()
let popover = navController.popoverPresentationController
popover?.sourceView = view
popover?.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height)
return navController
}
Note: The Navigation Controller is always presented, but just the first time I perform pushes. And this code is for be used in iPad.
Because of the nature of Storyboards and not being able to show that here, I'm not sure where your issue is exactly.
However I successfully setup a project that works using segues. I changed your code to the following:
func instantiateEditController(view : UIView) -> UINavigationController
{
if let popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("Edit Controller") as? MCMEditController {
popoverContent.preferredContentSize = CGSizeMake(320, 480)
let navController = UINavigationController(rootViewController: popoverContent)
navController.modalPresentationStyle = UIModalPresentationStyle.Popover
navController.navigationBar.tintColor = UIColor.whiteColor()
let popover = navController.popoverPresentationController
popover?.sourceView = view
popover?.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height)
return navController
} else {
return UINavigationController(rootViewController: self) // not recommend to keep this, I'm on Swift 1.2 and this was an easy fix to resolve the errors
}
}
To present this popover I set up this IBAction in my ViewController (sender in my case was a UIButton)
#IBAction func presentPopover(sender: AnyObject) {
if let view = sender as? UIView {
let controller = instantiateEditController(view)
let popover = UIPopoverController(contentViewController: controller)
popover.presentPopoverFromRect(view.frame, inView: self.view, permittedArrowDirections:UIPopoverArrowDirection.Any, animated: true)
}
}
The last thing that could be the issue is make sure your segues are using the segue type "show" for all the segues to make sure the transition between them use the navigation controller push:
Hope this helps!
Related
I am trying to create number pad in iPad using popover view controller. Everything is achieved but there is a shadow beneath the pop view. I tried to remove that shadow but nothing worked for me. Here is my code which presents pop over view in my view controller.
let vc = self.storyboard?.instantiateViewController(withIdentifier: "PopOverVC") as? PopOverVC
vc?.modalPresentationStyle = .popover
vc?.preferredContentSize = CGSize(width: 280, height: 425)
vc?.delegate = self
if let popoverPresentationController = vc?.popoverPresentationController {
popoverPresentationController.permittedArrowDirections = [.down, .up, .right, .left]
popoverPresentationController.sourceView = self.view
popoverPresentationController.sourceRect = txtNumber.frame
popoverPresentationController.delegate = self
if let popoverController = vc {
present(popoverController, animated: false, completion: nil)
}
}
Can anybody help me removing the shadow? Thanks in advance!!
I am NOT USING StoryBoard in my project. I have presented one view controller as popOver Style.
let vcOne = ViewControllerOne()
vcOne.showCorrectionFactor = true
vcOne.modalPresentationStyle = .popover
let pop = vcOne.popoverPresentationController
pop?.sourceView = self.view
pop?.sourceRect = sender.frame
vcOne.preferredContentSize = CGSize(width: 400, height: 500)
self.present(vcOne, animated: true, completion: nil)
Now i want to navigate to other view controller from ViewControllerOne() and with in this pop up.
I am doing it like
let vc = PairViewController()
self.navigationController?.pushViewController(vc, animated: true)
But self.navigationController? is getting nil value. How can i achieve this without story board.
You did not embed ViewControllerOne in a UINavigationController, so of course self.navigationController is nil.
Just do this:
// embed it!
let navController = UINavigationController(rootViewController: vcOne)
// get the popover presentation controller from the navigation controller!
let pop = navController.popoverPresentationController
pop?.sourceView = self.view
pop?.sourceRect = sender.frame
vcOne.preferredContentSize = CGSize(width: 400, height: 500)
// present navController rather than vcOne!
self.present(navController, animated: true, completion: nil)
I have implemented a menuViewVontroller for navigation drawer that works fine. I am able to render the view controllers on their respective menu buttons. I have one ViewController that loads up first and then I display other view controllers from the navigation menu i.e. Home menu displays the homeViewVontroller etc. as you can see in the screen shots.
But I also want my app to show the homeControllerView when the viewController loads. It is currently rendering an empty screen as the view controller is empty. When I write the below code in viewDidLoad() method, I am not getting the navigation drawer, just the homeViewController gets displayed (as shown in the picture below).
let view = UIView()
let controller = storyboard!.instantiateViewController(withIdentifier: "SliderController")
addChild(controller)
view.frame = self.view.bounds
self.view.addSubview(controller.view)
self.topView = view
What can I do to render both the homeViewController and the menuViewController in the same screen.
EDIT: My code when the user presses the menu item
#IBAction func didTapMenuButton(_ sender: UIBarButtonItem) {
guard let menuViewController = storyboard?.instantiateViewController(withIdentifier: "MenuViewController") as? MenuViewController else { return }
menuViewController.didTapMenuType = {
menuType in
self.transitionToNew(menuType)
}
menuViewController.modalPresentationStyle = .overCurrentContext
menuViewController.transitioningDelegate = self
present(menuViewController, animated: true)
}
func transitionToNew(_ menuType: MenuType) {
let title = String(describing: menuType).capitalized
self.title = title
topView?.removeFromSuperview()
switch menuType {
case .promotion:
let view = UIView()
view.backgroundColor = .yellow
view.frame = self.view.bounds
self.view.addSubview(view)
self.topView = view
case .billPayment:
let view = UIView()
view.backgroundColor = .blue
view.frame = self.view.bounds
self.view.addSubview(view)
self.topView = view
default:
break
}
}
I don't ask for a lot out of life, but I'd give a lot to know how to get a navigation bar on this popover:
Here's my storyboard:
And here's my code presenting the popover:
#IBAction func doButton(_ sender: Any) {
let vc = PopViewController()
vc.preferredContentSize = CGSize(width: 260,height: 300)
vc.modalPresentationStyle = .popover
vc.view.backgroundColor = UIColor.green
if let pres = vc.presentationController {
pres.delegate = (self as UIAdaptivePresentationControllerDelegate)
}
self.present(vc, animated: true)
if let pop = vc.popoverPresentationController {
pop.sourceView = (sender as! UIView)
pop.sourceRect = (sender as! UIView).bounds
pop.backgroundColor = vc.view.backgroundColor
}
}
}
extension ViewController : UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
}
(Thanks to #matt, BTW, for the above code!)
I've searched high and low on Google yet haven't found an answer that I could understand. I tried to add the nav bar in Storyboard, but no dice--the only element that would accept it was the prototype cell in the table view.
Please don't redirect to something written 7 years ago--I've already read most of them, and I'm using Swift now. Certainly, I may have overlooked a clear answer, and I'll be humble and contrite if that's the case. But meantime, I'd sure appreciate some help if ya got it!
Thanks!
Change your right tableview controller to a navigation controller with a tableViewController root. The navigation Controller gets an identifier : "navigation".
Now you can change the first code of doButton function, and keep the rest.
#IBAction func doButton(_ sender: Any) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "navigation") as! UINavigationController
vc.preferredContentSize = CGSize(width: 260,height: 300)
vc.modalPresentationStyle = .popover
vc.view.backgroundColor = UIColor.green
if let pres = vc.presentationController {
pres.delegate = (self as UIAdaptivePresentationControllerDelegate)
}
self.present(vc, animated: true)
if let pop = vc.popoverPresentationController {
pop.sourceView = (sender as! UIView)
pop.sourceRect = (sender as! UIView).bounds
pop.backgroundColor = vc.view.backgroundColor
}
}
finally , you will get the nav bar in your popover.
I have used navigation item in my app. In the log out method I have popped to root view controller i.e. my loginViewController but while doing so the navigation bar gets removed. I have tried putting the code to load in viewWillAppear but it is still not working. Could you please help me?
Here is my code for log out:
#IBAction func btnLogOutClicked(_ sender: Any) {
let log : LoginViewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
let window:UIWindow = UIApplication.shared.keyWindow!
let navControl : UINavigationController = window.rootViewController as! UINavigationController
if (!(navControl .isEqual(log)))
{
window.rootViewController = log
}
navControl.popToRootViewController(animated: true)
}
My viewWillAppear-
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.isNavigationBarHidden = false
self.navigationItem.hidesBackButton = true
self.navigationItem.title = "Select Client"
// create a new butto
let button: UIButton = UIButton(type: UIButtonType.custom)
//set image for button
button.setImage(UIImage(named: "logo-icon"), for: UIControlState.normal)
//set frame
button.frame = CGRect(x: 0, y: 0, width: 50, height: 30)
let barButton = UIBarButtonItem(customView: button)
//assign button to navigationbar
self.navigationItem.leftBarButtonItem = barButton
}
Here is my storyboard-
I am using pushViewController to reach to tab bar controller from login view controller
Try below code to change the NavigationController stack :
let oldVCs = self.navigationController?.viewControllers
let newVCs = [UIViewController]()
// Add your root VC in new array of VCs
newVCs.append(oldVCs![0])
// Add your new VC just after your root VC
let log : LoginViewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
newVCs.append(log)
self.navigationController?.setViewControllers(newVCs , animated: true)
In this the animation will be like pushing a new controller in stack.
If you want to completely leave that stack and create a new one:
let log : LoginViewController = self.storyboard?.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
let loginNavigationController = UINavigationController(rootViewController: log)
self.view.window?.rootViewController = loginNavigationController