I have a MapViewController that is basically a MKMapView and presents a map with custom annotations.
Right now I am trying to present another ViewController from the bottom containing additional filters that the user will be able to use on his journey.
However I ran into a problem, when I am presenting the new FilterMenuViewController as a child of MapViewController the MapViewController disappears.
This is what it looks like:
Initial state
Button to present new controller tapped
New controller presented but the MapViewController disappearing
The code that takes care of the interaction is as follows:
MapViewController variables declaration:
var filterMenuVC = FilterMenuViewController()
var isFilterMenuOpened = false
MapViewController viewDidLoad():
filterMenuVC = storyboard?.instantiateViewController(withIdentifier: "FilterMenuViewController") as! FilterMenuViewController
MapViewController showFilterMenu button action:
#IBAction func showFilterMenu(_ sender: UIButton) {
// Presents the filter menu
if isFilterMenuOpened == true {
isFilterMenuOpened = false
filterMenuVC.willMove(toParentViewController: nil)
filterMenuVC.view.removeFromSuperview()
filterMenuVC.removeFromParentViewController()
} else if isFilterMenuOpened == false {
isFilterMenuOpened = true
self.addChildViewController(filterMenuVC)
self.view.addSubview(filterMenuVC.view)
filterMenuVC.didMove(toParentViewController: self)
}
}
Try this, the view shows from top and reverse, here is the image: https://imgur.com/a/gzIGjEa
if isFilterMenuOpened{
if let searching = self.childViewControllers.first as? ViewController{
UIView.animate(withDuration: 0.7, animations: {
searching.view.frame = CGRect.init(x: 0,
y: self.view.frame.origin.y-308,
width: self.view.frame.size.width,
height: 308)
}, completion: {(boos) in
searching.removeFromParentViewController()
searching.dismiss(animated: true, completion: nil)
self.isFilterMenuOpened = false
})
}
}else{
let search = self.storyboard?.instantiateViewController(withIdentifier: "searchView") as! ViewController
search.view.frame = CGRect.init(x: 0, y: self.view.frame.origin.y-308, width: self.view.frame.size.width, height: 308) //The View controller height same size of your view in storyboard
search.delegateSearch = self
self.addChildViewController(search)
UIView.animate(withDuration: 0.5, animations: {
search.view.frame = CGRect.init(x: 0, y: self.view.frame.origin.y, width: self.view.frame.size.width, height: 308)
})
self.view.addSubview(search.view)
self.didMove(toParentViewController: search)
isFilterMenuOpened = true
}
The problem was that I created a segue "show" from the button to the ViewController which conflicted with adding the controller to the current view, it pushed into it instead and the MapViewController got deallocated.
So I just deleted the segue from sotryboard and added the child programatically, it works like charm now.
Was a stupid mistake, but maybe this will help someone who runs into the same problem :)
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!!
In want to have a button floating next to my Tab Bar. When pressed, this button will open a View that can be Navigated (so a View Controller embedded in a Navigation Controller(?)).
In UITabBarController {
ViewDidLoad() {
super.viewDidLoad()
//I have my 5 tab bar items set up programatically here.
//The middle tab bar item is disabled because the button is on top of it
setupMiddleButton()
}
My setupMiddleButton function
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 52, height: 52))
//..various styling and alignment values...
view.addSubview(menuButton)
menuButton.addTarget(self, action: #selector(menuButtonAction(sender:)), for: .touchUpInside)
finally I've tried to add the code to push the view controller, however I receive nil when tapping the button.
#objc private func menuButtonAction(sender: UIButton) {
let createController = CreateViewController()
let nav3 = UINavigationController(rootViewController: createController)
nav3.navigationController!.pushViewController(createController, animated: true)
I think that you may be passing the wrong parameter to the menuButtonAction function, try to change your code like this:
func setupMiddleButton() {
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 52, height: 52))
//..various styling and alignment values...
view.addSubview(menuButton)
menuButton.addTarget(self, action: #selector(menuButtonAction(_:)), for: .touchUpInside)
}
...
#objc private func menuButtonAction(_ sender: UIButton) {
...
}
So I figured it out. Turns out it was much simpler than I thought, which makes me think I was explaining myself poorly in the question. Anyway, here's the code that worked for me.
let myViewController = ViewController()
let nav = UINavigationController(rootViewController: myViewController)
self.present(nav, animated:true, completion: nil)
I am trying to add a view controller from top for that I have created a custom animation which works correctly. However, the background color of the view controller which is being added is setting to black, where as I just want it to be transparent so that the view controller below can be visible.
Here is the code to add custom animation:
let vc = Global.sharedInstance.storyboard.instantiateViewController(withIdentifier: "AnimationViewControllerID") as! AnimationViewController
vc.view.backgroundColor = UIColor.clear
vc.personName = name
let begin = CGRect(x: 0, y: -vc.view.frame.height, width: vc.view.frame.width, height: vc.view.frame.height)
let end = CGRect(x: 0, y: 0, width: vc.view.frame.width, height: vc.view.frame.width)
self.present(vc, animated: false) { () -> Void in
vc.view.frame = begin
vc.view.alpha = 0.5
vc.view.backgroundColor = UIColor.clear
UIView.animate(withDuration: 1, animations: { () -> Void in
vc.view.frame = end
},
completion: nil)
}
I tried setting the view controller's background color to clear but still, it's not making the background transparent.
You should set the presentation style of the presented view controller to accordingly.
Set it to overFullScreen if you want it to display over the current window and to overCurrentContext if you just want to set it above the view controller's context.
Also, you should set definesPresentationContext to true.
vc.modalPresentationStyle = .overFullScreen
vc.definesPresentationContext = true
I'm presenting a popover viewController on top of a UITableView. How can i dismiss this popover when tapped outside of it? I'm trying to call it from the didSelectRow method, but the tap isn't detected. Any suggestion?
Thanks!
this is my code:
let addFriendsPopoverViewController = storyboard?.instantiateViewController(withIdentifier: "HomePopOver") as! HomePopOverViewController
addFriendsPopoverViewController.index = (sender.tag)!
addFriendsPopoverViewController.delegate = self
addFriendsPopoverViewController.isModalInPopover = true
addFriendsPopoverViewController.modalPresentationStyle = UIModalPresentationStyle.popover
addFriendsPopoverViewController.preferredContentSize = CGSize(width: 210, height: 40)
let popoverMenuViewController = addFriendsPopoverViewController.popoverPresentationController
popoverMenuViewController!.permittedArrowDirections = .down
popoverMenuViewController!.delegate = self
popoverMenuViewController!.sourceView = self.view
popoverMenuViewController!.sourceRect = CGRect(
x: UIScreen.main.bounds.width - 105,
y: 50,
width: 1,
height: 1)
present(
addFriendsPopoverViewController,
animated: true,
completion: nil)
A view controller presented in a UIPopoverController, or presented using UIModalPresentationPopover, will automatically be dismissed when the user taps outside the popover, unless you have set isModalInPopover or implemented the delegate method which prevents it.
If you need some code to run when this happens, then you'll need to implement a delegate method too.
Which specific methods depend on whether you're using a UIPopoverController or UIModalPresentationPopover. The tags on your question suggest the former, but that's quite an old-fashioned (and deprecated) way of doing it.
Even though you have found your answer, I wanted to share my solution because I had the same problem and after I spent some time to figure it out, I have found what the problem was. It was not actually because of something missing but because of something is implemented in vain.
Although I don't know why it happens but if following method implemented in your code, that may cause popover not to dismiss by tapping anywhere else than UIBarButtonItem itself.
func prepareForPopoverPresentation(_ popoverPresentationController: UIPopoverPresentationController) {
popoverPresentationController.permittedArrowDirections = .any
popoverPresentationController.barButtonItem = UIBarButtonItem(customView: categoryButton)
}
Here's the rest of implementation I have made for popover:
extension SearchViewController:UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
func presentPopover(sender: UIButton) {
let popoverContentController = PopoverCategoryViewController()
let nav = UINavigationController(rootViewController: popoverContentController)
nav.modalPresentationStyle = UIModalPresentationStyle.popover
nav.isNavigationBarHidden = true
let popover = nav.popoverPresentationController
popover?.backgroundColor = ChaptifyColor.backgroundGray
popover?.delegate = self
popover?.sourceView = sender
popover?.sourceRect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: sender.bounds.width, height: sender.bounds.height))
popoverContentController.preferredContentSize = CGSize(width: 300, height: 300)
self.present(nav, animated: true, completion: nil)
}
}
I have a ParentViewController with a UISearchBar, and a ChildTableViewController with a tableView where the results from the search will be displayed. When I tap on the searchBar, a popover should present with all the results that conform to the filter written on the searchBar. This means, at the beginning, all results should be displayed in a popoverController.
The problem is that the results are shown occupying the whole screen, instead of being presented in a popover. Below is the code corresponding to ParentViewController where the popover should be presented.
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
let childController = ChildTableViewController()
childController.modalPresentationStyle = .Popover
childController.preferredContentSize = CGSize(width: 50, height: 100)
let popover = childController.popoverPresentationController
popover?.permittedArrowDirections = .Any
popover?.delegate = self
popover?.sourceView = self.view
popover?.sourceRect = CGRect(x: 200, y: 200, width: 1, height: 1)
presentViewController(childController, animated: true,completion: nil)
}
I am using Xcode 7 and iOS 9.
What you need to do is to implement the following method which is part of the UIPopoverPresentationControllerDelegate protocol:
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone; // This will force a popover display
}