How to present PopOver in iOS9 - ios

I am trying to create a pop over and when I present the view controller, the background is always solid black and the size is full screen.
I can't seem to figure out what's wrong and here is the code that I have
#IBAction func distancePopOver( sender : UIBarButtonItem){
//a UIViewController that I created in the storyboard
let controller = storyboard!.instantiateViewControllerWithIdentifier("distancePopOver")
controller.modalPresentationStyle= UIModalPresentationSTyle.PopOver
controller.preferredContentSize = CGSizeMake(200,30)
self.presentViewController(controller, animated: true, completion: nil)
//Configure the Popover presentation controller
let popController = (controller.popoverPresentationController)!
popController.permittedArrowDirections = UIPopoverArrowDirection.Down
popController.barButtonItem = sender
popController.delegate = self
}
Whenever I click on the UIBarButtonItem, it presents the view in full screen, but shouldn't it be the size I specify in line 5?

Popovers are quite finicky now. First, you are going to want to configure the popoverPresentationController before you present it.
Secondly, make sure your arrow direction is pointing the way the arrow points and not where the content is respective to the UIBarButtonItem. So, if its inside UIToolbar (and is near the bottom of the screen) you'll want .Down otherwise if its a navigation bar (near the top) you'll want to use .Up.
#IBAction func distancePopOver( sender : UIBarButtonItem){
//Configure the Popover presentation controller
let popController = (controller.popoverPresentationController)!
popController.permittedArrowDirections = .Down // .Up
popController.barButtonItem = sender
popController.delegate = self
//a UIViewController that I created in the storyboard
let controller = storyboard!.instantiateViewControllerWithIdentifier("distancePopOver")
controller.modalPresentationStyle = .Popover
controller.preferredContentSize = CGSizeMake(200,30)
presentViewController(controller, animated: true, completion: nil)
}
Now if you got this far and its still not working, its because the popover's default behavior in a compact size class is to fill the screen. Since you are already setting your view controller to be the popover's delegate you'll just need to implement this delegate function: adaptivePresentationStyleForPresentationController(_:traitCollection:) and return .None for the presentation style. This will allow you to even show a real looking popover on the iPhone. See my blog post: iPhone Popover for a full example of doing this.

Related

How to hide top space showing previous ViewController hierarchy on Xcode iOS Swift app?

This case not occurs on iPhone 6 but, occurs on iPhone 8 or higher. Using a segue of kind Show Detail to navigate from ViewController1 to ViewController2 there are a space showing the previous ViewController1 on top screen like image below:
How can I hide this space?
I tried:
Use all presentation types on ViewController2 (Automatic, FullScreen...)
Size master
You should try presenting it programatically as (set it in previous view controller):
let navVC = UINavigationController.init(rootViewController: vc)
navVC.modalPresentationStyle = .fullScreen
present(navVC, animated: true, completion: nil)
If you don't want to use navigation controller then skip first step.
Set the modalPresentationStyle of the UIViewController you're presenting as fullScreen.
class PresentingViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
modalPresentationStyle = .fullScreen
}
}
Here is how you can do it in storyboard...First tap the segue...first change kind to Modal... And then presentation to full screen ...
You could try:
let nav = UINavigationController()
let ctrl = ViewController1()
nav.pushViewController(ctrl, animated: true)
nav.modalPresentationStyle = .overCurrentContext
self.showDetailViewController(nav, sender: self)
nav.popoverPresentationController?.sourceView = self.view
This covers the complete screen when presenting your controller.
nav.popoverPresentationController?.sourceView = self.view
sets the source view of your popover to the size of the view.

How do I keep UI elements above a UIViewController and its presented ViewController?

I want to display some UI elements, like a search bar, on top of my app's first VC, and also on top of a second VC that it presents.
My solution for this was to create a ContainerViewController, which calls addChildViewController(firstViewController), and view.addSubview(firstViewController.view). And then view.addSubview(searchBarView), and similar for each of the UI elements.
At some point later, FirstViewController may call present(secondViewController), and ideally that slides up onto screen with my search bar and other elements still appearing on top of both view controllers.
Instead, secondViewController is presented on top of ContainerViewController, thus hiding the search bar.
I also want, when a user taps on the search bar, for ContainerViewController to present SearchVC, on top of everything. For that, it's straightforward - containerVC.present(searchVC).
How can I get this hierarchy to work properly?
If I understand correctly, your question is how to present a view controller on top (and within the bounds) of a child view controller which may have a different frame than the bounds of the parent view. That is possible by setting modalPresentationStyle property of the view controller you want to present to .overCurrentContext and setting definesPresentationContext of your child view controller to true.
Here's a quick example showing how it would work in practice:
override func viewDidLoad() {
super.viewDidLoad()
let childViewController = UIViewController()
childViewController.view.backgroundColor = .yellow
childViewController.view.translatesAutoresizingMaskIntoConstraints = true
childViewController.view.frame = view.bounds.insetBy(dx: 60, dy: 60)
view.addSubview(childViewController.view)
addChildViewController(childViewController)
childViewController.didMove(toParentViewController: self)
// Wait a bit...
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
let viewControllerToPresent = UIViewController()
viewControllerToPresent.modalPresentationStyle = .overCurrentContext // sets to show itself over current context
viewControllerToPresent.view.backgroundColor = .red
childViewController.definesPresentationContext = true // defines itself as current context
childViewController.present(viewControllerToPresent, animated: true, completion: nil)
}
}

MyScript how to add mathwidget as a subview inside another UIViewController

how to add mathwidget as a subview inside another UIViewController
Currently, mathwidget is working fine when loading UIViewController.
let subViewEE = MathWidgetClassName()
self.present(subViewEE, animated: true, completion: nil)
But when I am trying to add it as a subview inside present view controller nothing shows up, here is the code:
let mathWidget= MathWidgetClassName()
self.addChildViewController(mathWidget)
self.view.addSubview(mathWidget.view)
mathWidget.didMove(toParentViewController: self)
Can anyone help to display MathWidget as a subview in present UIViewController?
you are creating viewcontroller programmatically then you need to set frame and background color of it like,
let mathWidget = MathWidgetClassName()
mathWidget.view.bounds = self.view.bounds
mathWidget.view.backgroundColor = UIColor.green // you should set white here , it is for demonstration
self.addChildViewController(mathWidget)
self.view.addSubview(mathWidget.view)
mathWidget.didMove(toParentViewController: self)
If you have view controller in storyboard then you should do like,
let mathWidget = self.storyboard?.instantiateViewController(withIdentifier: "storyBoardID") //storyBoardID is Storyboard id - can be set from identity inspector of storyboard
// mathWidget?.view.bounds = self.view.bounds
// mathWidget?.view.backgroundColor = UIColor.green
self.addChildViewController(mathWidget!)
self.view.addSubview((mathWidget?.view)!)
mathWidget?.didMove(toParentViewController: self)

Swift SideMenu show view controller

So I'm having a table view controller and using https://github.com/jonkykong/SideMenu i'm trying to display a "slide in" sidebar which works, but it doesn't show me the view that I want in the sidebar is black
// Define the menus
let menuLeftNavigationController = UISideMenuNavigationController()
menuLeftNavigationController.leftSide = true
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration of it here like setting its viewControllers.
SideMenuManager.menuLeftNavigationController = menuLeftNavigationController
// Enable gestures. The left and/or right menus must be set up above for these to work.
// Note that these continue to work on the Navigation Controller independent of the View Controller it displays!
SideMenuManager.menuAddPanGestureToPresent(toView: self.navigationController!.navigationBar)
SideMenuManager.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
When It clicks on the sidebar button I have this, which creates the animation but doesn't show the viewcontroller
func someAction(){
present(SideMenuManager.menuLeftNavigationController!, animated: true, completion: nil)
debugPrint("clicked")
}
On the repo readme, you will find your answer, take a look on the Customization
section https://github.com/jonkykong/SideMenu#sidemenumanager.
Simply set menuFadeStatusbar = false
SideMenuManager.default.menuFadeStatusBar = false
From the previous link, you will find the following information : "Draws the menuAnimationBackgroundColor behind the status bar. Default is true.
If menuFadeStatusBar is true, this color is used to fade it. Default is black."
The answer is in the comment of the snippet you posted:
// UISideMenuNavigationController is a subclass of UINavigationController,
// so do any additional configuration of it here like setting its viewControllers.
let btnMenu:UIButton = UIButton()
btnMenu.frame = CGRect(x: 20*valuePro, y: 20*valuePro, width: 40*valuePro, height: 40*valuePro)
btnMenu.backgroundColor = .red
btnMenu.addTarget(self, action: #selector(self.displayMenu), for: .touchUpInside)
self.view.addSubview(btnMenu)
#objc func displayMenu(sender: UIButton!) {
print("Button Clicked")
present(SideMenuManager.default.menuLeftNavigationController!, animated: true, completion: nil)
}
https://github.com/jonkykong/SideMenu
The SideMenu README
Code Implementation
First:
import SideMenu
From a button, do something like this:
// Define the menu
let menu = UISideMenuNavigationController(rootViewController: YourViewController)
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration
// of it here like setting its viewControllers. If you're using storyboards, you'll want to do something like:
// let menu = storyboard!.instantiateViewController(withIdentifier: "RightMenu") as! UISideMenuNavigationController
present(menu, animated: true, completion: nil)
Answer
You need use UISideMenuNavigationController(rootViewController:), not UISideMenuNavigationController().
If you open the side menu from left, set leftSide to true.
let menu = UISideMenuNavigationController(rootViewController: YourViewController)
menu.leftSide = true
present(menu, animated: true, completion: nil)
Of course, you should give instance variable to UISideMenuNavigationController(rootViewController:).
I can recommend using JASidePanels
It's pretty simple and it just works. You're creating an JASidePanelController, setting this class to empty viewcontroller in your Storyboard and making this controller initial. (do not forget to import JASidePanels at the top of the class)
Then, in this class, you're implementing awakeFromNib() method like this:
leftPanel = ..//instantiating menu controller
let centerController = ...//instantiating center controller
centerPanel = UINavigationController(rootViewController: centerController)
That's it.
You can instantiate controller via their ID which can be set in Identity Inspector
let stb = UIStoryboard(name: "Main", bundle: nil) //instantiating a storyboard we will use for instantiating controllers
let someController = stb.instantiateViewController(withIdentifier: "here_your_identifier_goes") as! YourControllerClass

Get UIViewController.title to show in modally presented UINavigationController

I know this question gets asked a lot.
I've tried every answer (I think) and can't get a title to show up.
I have a static method I use to show view controllers modally.
I think I understand that a navigation controller gets its title from the title property of the view controller it is presenting, but I cannot get my vc's title to show up, and other methods I have tried aren't working, either.
static func present(vc vc: UIViewController) {
// The navCtrl presents a vc, and uses that title.
// I should be able to set this, right?
vc.title = "vc.title" // doesn't show up
vc.navigationItem.title = "vc.navigationItem.title" // nothing
vc.navigationItem.prompt = "vc.navigationItem.prompt" // doesn't show
vc.navigationController?.title = "vc.navigationController?.title" // nuttin'
let navCtrl = UINavigationController(rootViewController: vc)
navCtrl.navigationBar.tintColor = UIColor.whiteColor()
navCtrl.navigationBar.barTintColor = UIColor.blackColor()
navCtrl.navigationBar.translucent = false
// How about adding a UINavigationItem? Nope.
// let item = UINavigationItem(title: "UINavigationItem")
// navCtrl.navigationBar.pushNavigationItem(item, animated: true) // CRASH: Cannot call pushNavigationItem:animated: directly on a UINavigationBar managed by a controller.
// Can I set something on the navCtrl? Huh-uh. None of this works
navCtrl.navigationController?.title = "navCtrl.navigationController?.title"
navCtrl.navigationItem.prompt = "navCtrl.navigationItem.prompt"
navCtrl.title = "navCtrl.title"
navCtrl.navigationItem.title = "navCtrl.navigationItem.title"
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(navCtrl, animated: true, completion: nil)
}
No matter what I've tried, I just get an empty navigation bar with a close button:

Resources