iOS Swift Popup View Controller - ios

I need to have a ViewController slide up, be centered, and overlay the current ViewController. I thought the following code would work but it does not:
let view = storyboard?.instantiateViewControllerWithIdentifier("castSpell") as! CastSpellViewController
view.modalPresentationStyle = .OverCurrentContext
presentViewController(view, animated: true, completion: nil)
The new ViewController is shown but just as a full screen view. I have it's size set to 400x300 in the storyboard. I know I can do the same thing by having a view within a view and then showing the overlay view. Is that the route I need to go?

You need to set the presentation style on the presenter, not the presenting view.
Use self.modalPresentationStyle = .OverCurrentContext

let popOverVC = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewControllerWithIdentifier("ViewControllerName") as! PopOverViewContoller
self.addChildViewController(popOverVC)
popOverVC.view.frame = self.containerView.frame
self.containerView.addSubview(popOverVC.view)
popOverVC.didMoveToParentViewController(self)
Use the above code to add viewcontroller as a popover view. The container view is optional. I like using container views when the subviews position is fixed. I can position the container using autolayout and keep it hidden until needed.
In you case, you can place the container/subView at the bottom of the screen from where you need to slide up the subview.
UIView.animateWithDuration(0.5) { () -> Void in
//Animate here
}
Then change the frame of the container/subview inside the above block of code.
Note : Container view is just a normal UIView. I like naming it container :)

Related

Adding Custom popup doesn't filling the full view iOS, Swift

I have created a UIViewControlller and designed in storyboard, I want to show it as popup for my another view.
I used the following to show as popup:
guard let popupVC = UIStoryboard(name: "More", bundle: nil).instantiateViewController(withIdentifier: "LanguageSelectionViewController") as? LanguageSelectionViewController else{
fatalError("Unexpected destination VC")
}
self.addChildViewController(popupVC)
popupVC.view.frame = self.tableView.frame
print("POPUP Frame VIEW -- \(popupVC.view.frame)")
print("SElF VIEW -- \(self.tableView.frame)")
popupVC.view.frame = self.tableView.frame
print("POPUP Frame VIEW -- \(popupVC.view.frame)")
print("SElF VIEW -- \(self.view.frame)")
popupVC.modalPresentationStyle = .currentContext
popupVC.modalTransitionStyle = .crossDissolve
popupVC.view.bindFrameToSuperviewBounds()
self.view.addSubview(popupVC.view)
popupVC.didMove(toParentViewController: self)
It is working properly, but on my device half of the screen space is not filled by popup view.
Have you tried using the present() function? Something like this:
let popupVC = PopupViewController()
popupVC.modalPresentationStyle = .overFullScreen
popupVC.modalTransitionStyle = .crossDissolve
self.present(popupVC, animated: true, completion: nil)
I find designing view controllers in their own xib files easier, and it allows initialisation like in my example, rather than having to use the storyboard in code, but thats personal preference.
If it still isnt working, maybe check that the layout constraints for the popup's background are correct, so it actually fills it's parent.
You need to swap these two lines:
self.view.addSubview(popupVC.view)
popupVC.view.bindFrameToSuperviewBounds()
You can't bind a view to it's superview if the view hasn't been added to it yet.
First thing you need click on popup(storyboard or xib) and set it to background color .clear Color
Then make it to center. like
popupVC.center = self.view.center
it's just a guide you can change and set names accordingly. But my question why you are using storyboard why not have created Xib or View
Hope it will serve your purpose.

add subview over UITableView

First of, I am noob to Swift programming.
I am trying to show a custom view over a UITableView.
I am facing two major issues :
a) The subview does not appear correctly firstly. ref image below :
and after few moments actual view is loaded :
b) After the UITableView is scrolled, the view is not coming over the current top scroll position of UITableView
Following is the code to add subview :
let vaAdPopupViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AdPopupWithCrossViewController") as! AdPopupWithCrossViewController
vaAdPopupViewController.adID = adID
vaAdPopupViewController.tableView = self.tableView
if let message = parseJSON["adv_text"] as? String{
vaAdPopupViewController.message = message
}
let navigationBarFrame: CGRect = (self.navigationController?.view.frame)!
let frameSize = CGRect(x: navigationBarFrame.minX, y: navigationBarFrame.minY, width: navigationBarFrame.width, height: (navigationBarFrame.height - (self.navigationController?.navigationBar.frame.size.height)!))
vaAdPopupViewController.view.frame = frameSize
self.tableView.addSubview(vaAdPopupViewController.view)
vaAdPopupViewController.view.tag = 1000
self.addChildViewController(vaAdPopupViewController)
vaAdPopupViewController.didMove(toParentViewController: self)
also in AdPopupWithCrossViewController :
override func viewDidLoad() {
self.view.superview?.layoutIfNeeded()
self.view.layoutIfNeeded()
super.viewDidLoad()
}
Please guide me how to resolve this issue.
Thank You.
You probably want to either create a Present Modally Segue or use present() via code.
You've already created your AdPopupWithCrossViewController. Set its background color to be translucent. Then you can present it like this:
let vaAdPopupViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AdPopupWithCrossViewController") as! ModalOverTableViewController
vaAdPopupViewController.modalPresentationStyle = .overCurrentContext
self.present(vaAdPopupViewController, animated: true, completion: nil)
Then, your little "X" button can remove the ad with:
#IBAction func closeTapped(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
You can try out the various options on .modalPresentationStyle and .modalTransitionStyle, as well as setting animated to true or false, to get the appearance / behavior you desire.
As Dan says, you should add your popup as a subview of the view controller's view, not of the table view. A Table view's view hierarchy is private and you should not be trying to mess with it.
Note that you can't do this with a table view controller. This has always bugged me, but it's a fact: A UITableViewController manages a single table view and nothing else. If you want a more complex view hierarchy you need to embed your table view controller in another view controller. I do this with a container view and an embed segue, which is very easy.
If you do that then you can add your new view controller's content to the parent view controller's content view, not to the table view controller's view (or to the table view itself)

Instantiating ViewController from new storyboard

I have just made a small transition so my project loads a different storyboard as its main (did it in the info.plist).
I have my new storyboard to keep my viewController that are responsible for login screen etc. Just to make it more clear.
After the login button is tapped I want to initiate a navigationController from another storyboard:
func instantiateViewController(fromStoryboard storyboard: String, withIdentifier identifier: String) -> UIViewController! {
let storyboard = UIStoryboard(name: storyboard, bundle: nil)
let viewController = storyboard.instantiateViewControllerWithIdentifier(identifier)
return viewController
}
#IBAction func loginButtonTapped(sender: UIButton) {
let viewController = instantiateViewController(fromStoryboard: "Main", withIdentifier: "MainNavigationController")
presentViewController(viewController, animated: true, completion: nil)
}
Everything works correctly but one thing is driving me nuts.
After presenting the MainNavigationController from Main.storyboard its view hierarchy is not maintained.
What I mean is, the labels and buttons which supposed to be on top of another, full screen UIView (but are not its child and so they should remain) are now behind it.
What might be causing this and what is the simplest way to make them appear on top (as they do whey I open main.storyboard)
EDIT
I added a line of code in the rootView of the MainNavigationController in its viewDidLoad method:
self.view.sendSubviewToBack(wholeScreenView)
and it solved the problem.
However, does anybody know why do I have to code it myself and the views are not like in the Main.storyboard?
The storyboard is not configured the way you think it is. Your wholeScreenView is in fact in front of the other views, in the storyboard. The other views (the labels and buttons) are not subviews of wholeScreenView; they are subviews of the main view, and so is wholeScreenView. It is a later subview, so it is in front of them.

addSubview can not correctly show all the content in the viewController?

In my case, my view hierarchy:
UIViewController
View
container view + button
(in container view) tableview
I want to present this view controller as left slide menu
let storyboard = UIStoryboard(name: "SlideMenu", bundle: nil)
let leftSlideMenu = storyboard.instantiateViewControllerWithIdentifier("leftSlideMenu") as! LeftSlideMenu
leftSlideMenu.view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, 100, view.superview!.frame.size.height)
// this line is set the slide menu to right frame to only take a part of screen and looks like a "Slide Menu"
presentViewController(leftSlideMenu, animated: false, completion: nil)
// this is good and show all content in the view controller but the frame is not in control
When I use this, it only show button but not show table view
view.addSubview(leftSlideMenu.view)

Load View controller in xib file

I was wondering if i could make some sort of a segue between these 2 views in a Xib file.
the main View is loaded into a scrollview in the storyboard.
.
(so if ik click Bewerken(edit) i would get pushed to the view controller on the right)
Thanks!
I would suggest changing this to a Container View inside the storyboard instead of a separated Xib. You can add and position/size UIContainerView as a subview and add a"Storyboard Embed Segue to attach another ViewController. This is what it will look like in IB/Storyboard:
During runtime, the blue UIView (or the embedded UIViewController if you like) will be embedded in the hosting UIView as a subview:
If you change your implementation to this, you are in the beautiful segue world where you can just drag-and-drop segues :)
You could do 2 things:
1 - Wrap the main view in a Navigation Controller so you can do the following:
#IBAction func loadEditController(sender:UIButton){
let editController = RegisterController(nibName:"RegisterXIB", bundle:nil)
navigationController?.pushViewController(editController, animated: true)
}
2 - Present the Edit Controller over the current context and animate it yourself
#IBAction func loadEditController(sender:UIButton){
let editController = RegisterController(nibName:"RegisterXIB", bundle:nil)
editController.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
presentViewController(editController, animated: false, completion: nil)
//Move it offscreen and the animate it here
}

Resources