showViewController method only displays modal views - ios

Looking at Apples Resource for using showViewController() versus presentViewController() I can't seem to figure out my issue here.
I want to display a viewController from my storyboard programmatically by doing the following:
if let resultController = storyboard!.instantiateViewControllerWithIdentifier("mainTab") as? TabBarController {
showViewController(resultController, sender: UIBarButtonItem.self)
}
This works fine. However, it's presentation is always modal. Covering the screen vertically from bottom to top like so:
I was/still am under the impression that I should use showViewController to display a screen without the animation... But clearly I'm missing something here. All I want to do is display the VC non-modally. I feel like I've tried everything to no avail.
Thanks for the advice in advance.

I think you want to use something like this.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("Controller") as! UIViewController
self.presentViewController(vc, animated: false, completion: nil) // no animation or presentation as modal because animated is false
The key is to have animated set to false. This method works for me. Hope this helps!

Related

Swift modal view background appearing black after setting it to clear

I am trying to present a custom view from a controller modally, however when I do so the background of everything but the textfield I have turns black as seen in here . (the intended modal)
This seems to be a fairly common problem, however I have already implemented the code that most similar questions pose as the answer
here is my addEvent method in the first controller:
#IBAction func addEvent(_ sender: Any) {
let newEventViewController = NewEventViewController()
newEventViewController.view.backgroundColor = UIColor.clear
newEventViewController.view.isOpaque = false
navigationController?.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
navigationController?.present(newEventViewController, animated: true, completion: nil)
}
Any help figuring out what I am missing would be appreciated. If it makes a difference I am creating my app using individual xib files and not a storyboard.
You need to set the modalPresentationStyle of newEventController not the navigationController like this:
newEventViewController.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
Also although not needed I would present from self rather than the navigation controller like this:
self.present(newEventViewController, animated: true, completion: nil)

Container View Page Controller is Being Clipped instead of Resized

I am about fifteen seconds away from flipping over my desk and rage quitting, because I just cannot figure this out.
I have a Page View Controller as the embed of a Container View Controller. Sounds easy, right?
Problem is, the Page View Controller is getting clipped. I need it to resize. So they would be cute little pages with their full VC content.
I've tried every option on the Storyboard Display... things.
Here's a couple of pics to describe the problem:
Now I would share the code with you, but all it is the loading of the (single) page. The page does exist in a different storyboard, but even when I changed the view for View Controllers in the Main storyboard, they were still being cut off.
override viewDidLoad() {
let storyboard = UIStoryboard(name: "TEMPLATES", bundle: Bundle.main)
let vc = storyboard.instantiateViewController(withIdentifier: "template1")
self.setViewControllers([vc!], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
self.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] //Some code I found on Stack Overflow that did nothing
super.viewDidLoad()
}
Any help would be appreciated!
if you add it from the storyboard - it will just work.
if you add the child view controller from code - you also need to set the frame like so:
carsTableVC.view.frame = self.container.bounds
here is a full code example (carsTableVC is in a container):
let sb = UIStoryboard.init(name: "Cars", bundle: nil)
self.carsTableVC =
sb.instantiateViewController(withIdentifier:
"CarsTableViewController") as? CarsTableViewController
carsTableVC.view.frame = self.container.bounds
carsTableVC.willMove(toParent: self)
addChild(carsTableVC)
carsTableVC.didMove(toParent: self)
container.addSubview(carsTableVC.view)

Programatically creating Segues in ios swift

In my app I use side bar as in facebook. when the user slides out the side bar a uiimageview is displayed. when user taps on the image it takes hm to a different viewcontroller. the problem i am facing is that I have created sidebar programatically and the other view to which I want to navigate the user is created using storyboard. So my source view is created programatically and destination view is created using storyboard. So can someone explain me if there is any way of using "Segue" in this scenario. Since i can not create segue using storyboard I need to do it programatically but even after a lot of googling i could not find the answer.
Well, to get another instance of another storyboard programmatically you can use something like:
let newController = UIStoryboard(name: "MyStoryboard", bundle: nil).instantiateViewControllerWithIdentifier("MyIdentifier") as! MyViewController
and then you push to your navigation controller, or add as a child view controller or something...
If you don't wanna bother with identifiers you can just use the instantiateInitialViewController instead of instantiateViewControllerWithIdentifier
Might help
"userSB" is the viewcontroller storyboard identifier
#IBAction func tapSearchCriteria(_ sender: Any?) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let aVC = storyboard.instantiateViewController(withIdentifier: "userSB") as? AViewController
aVC?.modalPresentationStyle = UIModalPresentationStyle.custom
aVC?.transitioningDelegate = self
aVC?.udelegate = self
self.present(aVC!, animated: true, completion: nil)
}

Trigger events when ViewController covered by a presented ViewController

I would like to process code when a ViewController is no longer visible due to presenting a new ViewController.
I cannot use ViewWillDisappear etc since the controller is not technically ever dismissed from the stack - you just can't see it.
What process can I use so that code runs when the controller is no longer visible (i.e. topmost) and when it becomes visible again?
EDIT:
Seems some confusion here - not sure why.
I have a viewcontroller.
I use the following code to present another controller
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navController = storyboard.instantiateViewControllerWithIdentifier("NavController") as! UINavigationController
let thisController = navController.viewControllers[0] as! MyController
self.presentViewController(navController, animated: true, completion: nil)
This controller does not trigger a viewWillDisappear on the previous controller since the previous view is not removed - just hidden.
I need to process code when this view is hidden (i.e. not visible) and, more importantly, process code when it becomes visible again.
When presenting a UIViewController if the presentation style has been set to UIModalPresentationOverCurrentContext it doesn't call the viewWillDisappear and related methods as the view never disappears or gets hidden.
A simple test to check if thats the case would be to set the NavController that you are using to have a clear background color. If you do this and present the NavController and you can still view the first UIViewController below your NavController content. Then you are using UIModalPresentationOverCurrentContext and that is why the viewDidDisappear isn't called.
Have a look at the answer referenced by Serghei Catraniuc (https://stackoverflow.com/a/30787112/4539192).
EDIT: This is in Swift 3, you can adjust your method accordingly if you're using an older version of Swift
If you won't be able to figure out why viewDidAppear and viewDidDisappear are not called, here's a workaround
protocol MyControllerDelegate {
func myControllerWillDismiss()
}
class MyController: UIViewController {
var delegate: MyControllerDelegate?
// your controller logic here
func dismiss() { // call this method when you want to dismiss your view controller
// inform delegate on dismiss that you're about to dismiss
delegate?.myControllerWillDismiss()
dismiss(animated: true, completion: nil)
}
}
class PresentingController: UIViewController, MyControllerDelegate {
func functionInWhichYouPresentMyController() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navController = storyboard.instantiateViewController(withIdentifier: "NavController") as! UINavigationController
let thisController = navController.viewControllers[0] as! MyController
thisController.delegate = self // assign self as delegate
present(navController, animated: true, completion: {
// place your code that you want executed when it disappears here
})
}
func myControllerWillDismiss() {
// this method will be called now when MyController will dismiss
// place your code that you want executed when it re-appears here
}
}
Firstly, thanks to Serghei for his time in helping work through this.
To clarify, both my potential presented controllers were set to Full Screen presentation style in the storyboard, however one was being set to Custom via a piece of pasted code dealing with the presentation. I can't find the error with the other.
However, if I force a presentation style of Full Screen as part of the presenting process then all is ok.
Hopefully my frustrating afternoon can help to save someone else's - always try to understand the implications and processes involved in pasted snippets.

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.

Resources