I am making a NSPopover, and have made it so I can transition between view controllers with a sliding animation using a parent view controller with my view controllers as children. It works well, except before I added this, the popover automatically resized to my view's size, but now, the popover is stuck at a fixed size.
The code for creating the popover:
self.homeVC = PopoverViewController(nibName: "PopoverViewController", bundle: nil)
self.loginVC = SignInViewController(nibName: "SignInViewController", bundle: nil)
self.containerView.view.wantsLayer = true
self.containerView.view.frame = self.homeVC!.view.bounds
self.containerView.addChildViewController(self.homeVC!)
self.containerView.view.addSubview(self.homeVC!.view)
popover.contentViewController = self.containerView
The code for transitioning the view controllers:
self.loginVC!.view.frame = self.homeVC!.view.bounds
self.containerView.addChildViewController(self.loginVC!)
let transition: NSViewControllerTransitionOptions = .SlideLeft
self.containerView.transitionFromViewController(self.homeVC!, toViewController: self.loginVC!, options: transition, completionHandler: { finished in
self.homeVC!.view.removeFromSuperview()
self.homeVC!.removeFromParentViewController()
self.containerView.view.bounds = self.loginVC!.view.bounds
})
Is there anyway that I can make the popover automatically resize to the size it is supposed to be after transitioning?
Thanks in advance.
I was able to fix it by instead of explicitly setting the frame, setting constraints to make the container view match the child's size.
Related
What's the difference between adding a viewcontroller's view inside another view controller's view and embedding a view controller like this:
addChildViewController(controller)
self.view.addSubview(controller.view)
controller.view.frame = view.bounds
controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
controller.didMove(toParentViewController: self)
Embedding a view controller (View Controller Containment) has added benefits such as calls being made to viewDidAppear, viewDidDisappear and rotation and resizing events being passed to the view controller to handle. These don't happen when you just add a view directly.
In my code I am using the present(:animated:completion:) method to present ViewController2 from ViewController1 that is the root view controller of a container view nested within RootViewController.
I've set the presentation style to be .coverVertical and I have ViewController1's definesPresentationContext variable set to true in it's viewDidLoad() method. I also have ViewController2's presentation set to .overCurrentContext. This makes ViewController2's bounds the same as ViewController1's but for whatever reason the .coverVertical animation starts at the bottom of the screen instead of starting from the bottom of ViewController1's frame.
However, this goes away when I set the root view controller of the container view to be a UINavigationController and nest ViewController1 within it. I assume this means that there is some second context variable that I'm missing that prevents the animations from animating overtop other views, but I couldn't seem to find any other variables besides definesPresentationContext.
So you are saying that your view controller hierarchy is
RootViewController
ViewController1
In that case, run this code inside ViewController1:
let vc = // ViewController2 instance, obtained somehow
vc.modalTransitionStyle = .coverVertical
self.definesPresentationContext = true
vc.modalPresentationStyle = .currentContext
self.present(vc, animated: true)
You will see that only the area of ViewController1's view is involved in the transition.
Note that the clipsToBounds of the container view must be set to true. If there is no container view, add one (to provide the clipping) — though I believe, from your description, that there is one (i.e. that you configured this in a storyboard).
So I have a vertical stack view in a simple layout. When I add a view through Interface Builder I see the view in the stack view no issues.
When I then add views programmatically to the UIStackView it breaks the constraints and the added views appear at the top of the window. I'm confused as to why it would break the constraints of the stack view.
func buildCats(theJson:JSON){
//self.verticalStack.subviews.forEach({ $0.removeFromSuperview() })
print(theJson)
if let infos = self.swiftyJsonvar["info"].array{
for info in infos{
guard let v = UINib(nibName: "ticketOrderView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as? UIView else { return }
v.translatesAutoresizingMaskIntoConstraints = false
self.verticalStack.addArrangedSubview(v)
}
}
}
The added subviews need constraints, as they have no intrinsic size. Try:
v.heightAnchor.constraint(greaterThanOrEqualToConstant: 30).isActive = true
v.widthAnchor.constraint(greaterThanOrEqualToConstant: 200).isActive = true
Hmmm.... I'm doubting this now... I suspect the issue may be related to adding the views on a background thread. Maybe run the loop on the main thread?
Edit 2: Ah... the problem I'm betting now is related to what you're doing with the view / subviews inside your "ticketOrderView"
For an example, see: https://github.com/DonMag/ScratchPad
I simply want to present a small option dialog over an existing main UIViewController/UIView , so that on an IPad I would see a small Dialog and in the Background I will see the Main View.
I managed to show a UIViewController/UIView in a modal view style as follow:
func showoptions(){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("Options") as! UIViewController
controller.modalPresentationStyle = UIModalPresentationStyle.Popover
let popoverPresentationController = controller.popoverPresentationController
// result is an optional (but should not be nil if modalPresentationStyle is popover)
if let _popoverPresentationController = popoverPresentationController {
// set the view from which to pop up
_popoverPresentationController.sourceView = self.view;
//_popoverPresentationController.sourceRect = CGRectMake(60, 100, 500, 500)
//_popoverPresentationController. .setPopoverContentSize(CGSizeMake(550, 600), animated: true)
//_popoverPresentationController.sourceView.sizeToFit();
// present (id iPhone it is a modal automatic full screen)
self.presentViewController(controller, animated: true, completion: nil)
}
}
But I have still some issues:
1. Howto get rid of the arrow shown at the border.
2. Howto size this modal view. It is shown to small and I would like to fit it to the largest controls in the UIControllerView/UIView.
any help ?
Try changing _popoverPresentationController.permittedArrowDirections to empty option set
Change controller.preferredContentSize to match your desired size
I needed something similar and ended up presenting a view controller as a modal with a transparent background over the current context. There I made a smaller opaque UIView with what I wanted.
I'm trying to add ViewControllers in UIScrollView and VC's are loaded from xib. This is my code
let onevc = OneViewController()
self.addChildViewController(onevc )
self.scrollView.addSubview(onevc .view)
onevc.didMoveToParentViewController(self)
let twovc = TwoViewController()
var frame:CGRect = twovc.view.frame
frame.origin.x = 320
twovc.view.frame = frame
self.addChildViewController(twovc)
self.scrollView.addSubview(twovc.view)
twovc.didMoveToParentViewController(self)
self.scrollView.contentSize = CGSizeMake(640, self.view.frame.size.height)
self.scrollView.pagingEnabled = true
Both the viewcontrollers are added but they are not visible, scrollview is just showing white screen. I have added few elements in ViewControllers and also to test I added println("something") So when the view is loaded, It is printing something but not showing anything. what am I doing wrong here?
Perhaps you forgot to specify the nib name for the view controller?
let onevc = self.storyboard!.instantiateViewControllerWithIdentifier("OneViewController")
or
let onevc = OneViewController(nibName: "OneViewController", bundle: nil)
Same goes for the 2nd one.