Swift presentViewController
Asked Answered
S

14

84

I programatically have multiple View Controllers in an iOS Swift Project. I do not have the storyboards and would like to avoid them if possible. Is there a way to switch to another viewcontroller.swift file (We will call it view2.swift) and have it be part of a function that a button calls?
I have tried the following:

let storyboard: UIStoryboard = UIStoryboard(name: "myTabBarName", bundle: nil)
let vc: UIViewController = storyboard.instantiateViewControllerWithIdentifier("myVCID") as UIViewController
self.presentViewController(vc, animated: true, completion: nil)

The above works with storyboards, but I want another view2.swift to be called. Can this be done?

Stoller answered 7/6, 2014 at 16:56 Comment(0)
M
130

Try this:

let vc = ViewController() //change this to your class name
self.presentViewController(vc, animated: true, completion: nil)

With Swift3:

self.present(vc, animated: true, completion: nil)
Molliemollify answered 7/6, 2014 at 16:59 Comment(13)
I'd recommend using the initializer: ViewController(nibNameOrNil: nil, bundleOrNil: nil)Degrading
Thank you! This ended up working. It is also much simpler than the old way to do it in Objective-C, which I guess was the whole point of swift. Thanks again!Stoller
@Adam, I am doing exactly same to show view on a button click. It shows up black blank screen. There are no errors. Any idea why am I getting black screen?Irrefragable
@Sanjivani, From iOS7, the default color of the view is clear color, So it show black screen. Set color in VIewController's viewDidLoad as override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.greenColor() }Fruit
this will occur blank screen !Somerville
@Irrefragable you have explicitly type the nib file name, so instead of "let vc = ViewController()" type "let vc = ViewController(nibName: "ViewController", bundle: nil)". This will solve your problem.Valdez
How is this accepted and vote up so many times, its not even using initializer for viewcontroller, do like this will result in nothingHowlan
Value of type 'AppDelegate' has no member 'present'Fiasco
@Oleksandr AppDelegate is not a view controller. You could try self.rootViewController.present( ... but this can depend on your use case and your app architecture.Molliemollify
Totally wrong approach, with this method, you only create a new ViewController instance not VC in the storyboard.Strouse
@OnderOZCAN this is exactly right approach when you don’t use storyboardsMolliemollify
Oh sorry I missed the title "Programmatically" my bad :(Strouse
If you get a black screen is because you are not instantiating your controller form a xib/nib/storyboardAlysaalyse
B
112

For those getting blank/black screens this code worked for me.

    let vc = self.storyboard?.instantiateViewController(withIdentifier: myVCID) as! myVCName
    self.present(vc, animated: true, completion: nil)

To set the "Identifier" to your VC just go to identity inspector for the VC in the storyboard. Set the 'Storyboard ID' to what ever you want to identifier to be. Look at the image below for reference.

Buoy answered 9/10, 2014 at 19:40 Comment(1)
@KD. except that the question asked to do it without storyboards.Limburger
M
21

For reference, because this question is one of the first Google result.

Breaking change in Swift 3:

The method presentViewController is replaced by the method present.

You can use it like the old one:

self.present(viewControllerToPresent, animated: true, completion: nil)

Example to open the camera:

let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
Monamonachal answered 6/10, 2016 at 8:0 Comment(0)
L
19

Swift 3 and Swift 4

let vc = self.storyboard?.instantiateViewController(withIdentifier: "idMyViewControllerName") as! MyViewControllerName
self.present(vc, animated: true, completion: nil)
Lacerated answered 9/12, 2016 at 8:54 Comment(0)
C
8

For me, I had two views in two separate nav controllers. I had to use a combination of the above.

var vc = self.storyboard?.instantiateViewControllerWithIdentifier("WelcomeViewController") as! WelcomeViewController
    var navigationController = UINavigationController(rootViewController: vc)
    self.presentViewController(navigationController, animated: true, completion: nil)

Swift 3.x

        let secondVC = self.storyboard?.instantiateViewController(withIdentifier: "VC-ID" as! yourViewController
        let navigationVC = UINavigationController(rootViewController: secondVC)
        self.present(navigationVC, animated: true, completion: nil)
Cenozoic answered 13/12, 2015 at 14:49 Comment(0)
C
6

Using Swift 2.1+

 let vc = self.storyboard?.instantiateViewControllerWithIdentifier("settingsVC") as! SettingsViewController
 self.presentViewController(vc, animated: true, completion: nil)

enter image description here

Charissecharita answered 3/11, 2015 at 0:49 Comment(0)
L
4

Solved the black screen by adding a navigation controller and setting the second view controller as rootVC.

let vc = ViewController()       
var navigationController = UINavigationController(rootViewController: vc)
self.presentViewController(navigationController, animated: true, completion: nil
Luxurious answered 6/3, 2015 at 23:56 Comment(0)
M
4

Just use this : Make sure using nibName otherwise preloaded views of xib will not show :

var vc : ViewController = ViewController(nibName: "ViewController", bundle: nil) //change this to your class name

 self.presentViewController(vc, animated: true, completion: nil)
Mori answered 24/5, 2015 at 3:30 Comment(0)
I
1

You don't need to instantiate the ViewController in Storyboard just to get present() ViewController to work. That's a hackish solution.

If you see a black/blank screen when presenting a VC, it might be because you're calling present() from viewDidLoad() in the First/RootViewController, but the first View isn't ready yet.

Call present() from viewDidAppear to fix this, i.e.:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let yourVC = YourViewController()
    self.present(yourVC, animated: true, completion: nil)
}

Once any "View" has appeared in your App, you can start calling present() from viewDidLoad().


Using UINavigationController (as suggested in an answer) is another option, but it might be an overkill to solve this issue. You might end up complicating the user flow. Use the UINavigationController based solution only if you want to have a NavigatonBar or want to return to the previous view controller.

Irons answered 9/9, 2018 at 16:57 Comment(0)
H
1

It's already answered. But adding one more thing while presenting a UIViewController, If anyone is trying to add UIModalPresentationStyle :

if directly presenting the UIViewController as fullScreen:

let viewController = UIViewController()
viewController.modalPresentationStyle = .fullScreen
self.present(viewController, animated: true)  

If there is UINavigationController with root view controller as UIViewController:

let viewController = UIViewController()
let navigationController = UINavigationController(rootViewController: viewController)
navigationController.modalPresentationStyle = .fullScreen
self.present(navigationController, animated: true)

More helpful answers:

Hetman answered 16/7, 2022 at 10:21 Comment(0)
M
0

You can use below code :

var vc = self.storyboard?.instantiateViewControllerWithIdentifier("YourViewController") as! YourViewController;
            vc.mode_Player = 1
            self.presentViewController(vc, animated: true, completion: nil)
Marhtamari answered 5/9, 2015 at 8:24 Comment(0)
B
0

Another possibility is that you do not have the XIB included in your Build target (which is what happened to me).

This could happen if you have a different target for Dev, Test & Release Builds (which you should have anyway).

Breakout answered 21/5, 2016 at 22:18 Comment(0)
S
0

I had a similar issue but in my case, the solution was to dispatch the action as an async task in the main queue

DispatchQueue.main.async {
    let vc = self.storyboard?.instantiateViewController(withIdentifier: myVCID) as! myVCName
    self.present(vc, animated: true, completion: nil)
}
Sideswipe answered 27/7, 2020 at 22:45 Comment(0)
S
-1

You can use code:

if let vc = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as? secondViewController {
   let appDelegate = UIApplication.shared.delegate as! AppDelegate
   appDelegate.window?.rootViewController = vc
}
Stevenson answered 30/10, 2017 at 3:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.