¿Cómo puedo cargar storyboard programáticamente desde la clase?

183

Mi problema es que estaba buscando la manera de usar storyboard y xib . Pero no puedo encontrar la manera adecuada de cargar y mostrar el guión gráfico mediante programación. El proyecto comenzó a desarrollarse con xib, y ahora es muy difícil anidar todos los archivos xib en el guión gráfico. Así que estaba buscando una manera de hacerlo en código, como con alloc, init, pushviewControllers. En mi caso, solo tengo un controlador en storyboard: UITableViewControllerque tiene celdas estáticas con algún contenido que quiero mostrar. Si alguien conoce la forma correcta de trabajar tanto con xib como con storyboard sin una gran refactorización, agradeceré cualquier ayuda.

kokoko
fuente

Respuestas:

370

En su guión gráfico, vaya al inspector de atributos y configure el identificador del controlador de vista. Luego puede presentar ese controlador de vista utilizando el siguiente código.

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"myViewController"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
James Beith
fuente
65
[sb instantiateInitialViewController]es útil si desea comenzar en el controlador de vista predeterminado de la escena.
empalagoso
James, gracias! He estado buscando durante bastante tiempo tratando de descubrir cómo instanciar la vista de un Storyboard. Su respuesta (y la pregunta de Kokoko) son muy refrescantes de encontrar.
bejonbee
En el código de James Beith, uno debe reutilizar ese UIViewControler * vc si se cambia de un lado a otro con el controlador de vista actual. Descubrí por las malas que el vc se queda y está conectado a la plumilla del guión gráfico hasta que el usuario presiona un botón en la nueva vista, y ahora hay una pérdida de memoria con ese vc descartado de los encantamientos anteriores de este código.
SWoo
11
En caso de que alguien quiera saber cómo hacer esto en el delegado de la aplicación, reemplace la [self presentViewcontroller]lógica con estas líneas en el siguiente orden: 1) self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];2) self.window.rootViewController = vc;y 3) [self.window makeKeyAndVisible];. Probablemente también pueda deshacerse de la modalTransitionStylelínea porque esta no es una transición modal del delegado de la aplicación.
lewiguez
Para su información, si desea "empujar" el nuevo guión gráfico en lugar de aparecer de manera modal, mire la respuesta de chaithraVeeresh.
Adam Johns
76

Swift 3

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "viewController")
self.navigationController!.pushViewController(vc, animated: true)

Swift 2

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("viewController")
self.navigationController!.pushViewController(vc, animated: true)

Requisito previo

Asigne una ID de Storyboard a su controlador de vista.

ID del guión gráfico

IB> Mostrar el inspector de identidad> Identidad> ID del guión gráfico

Swift (legado)

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("viewController") as? UIViewController
self.navigationController!.pushViewController(vc!, animated: true)

Editar: Swift 2 sugerido en un comentario por Fred A.

si desea usar sin ningún control de navegación, debe usarlo de la siguiente manera:

    let Storyboard  = UIStoryboard(name: "Main", bundle: nil)
    let vc = Storyboard.instantiateViewController(withIdentifier: "viewController")
    present(vc , animated: true , completion: nil)
Arquitecto Swift
fuente
1
En Swift 2, no necesita agregar "como? UIViewController", el compilador lo determina automáticamente
Frédéric Adda
2
o simplemente puede hacer self.storyboardy fusionar las líneas 1 y 2
Miel
17

En el inspector de atributos, proporcione el identificador para ese controlador de vista y el siguiente código funciona para mí

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
DetailViewController *detailViewController = [storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
[self.navigationController pushViewController:detailViewController animated:YES];
chaithraVeeresh
fuente
5

Prueba esto

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:@"Login"];

[[UIApplication sharedApplication].keyWindow setRootViewController:vc];
Adetiloye Philip Kehinde
fuente
Use esto si no está usando un UINavigationController como se muestra en otras respuestas
latenitecoder
2

en Swift
NavigationController y pushController puede reemplazar por

present(vc, animated:true , completion: nil)
Tarik
fuente
1

Para swift 3 y 4 , puede hacer esto. Una buena práctica es establecer el nombre de Storyboard igual a StoryboardID.

enum StoryBoardName{
   case second = "SecondViewController"
}
extension UIStoryBoard{
   class func load(_ storyboard: StoryBoardName) -> UIViewController{
      return UIStoryboard(name: storyboard.rawValue, bundle: nil).instantiateViewController(withIdentifier: storyboard.rawValue)
   }
}

y luego puedes cargar tu Storyboard en tu ViewController de esta manera:

class MyViewController: UIViewController{
     override func viewDidLoad() {
        super.viewDidLoad()
        guard let vc = UIStoryboard.load(.second) as? SecondViewController else {return}
        self.present(vc, animated: true, completion: nil)
     }

}

Cuando cree un nuevo Storyboard, simplemente configure el mismo nombre en StoryboardID y agregue el nombre de Storyboard en su enumeración " StoryBoardName "

Gandhi Mena
fuente
0

Siempre puede saltar directamente al controlador raíz:

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateInitialViewController];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
usuario938797
fuente
0

La extensión a continuación le permitirá cargar Storyboarday está asociada UIViewController. Ejemplo: si tiene un UIViewControllernombre ModalAlertViewControllery un guión gráfico llamado "alerta modal", por ejemplo

let vc: ModalAlertViewController = UIViewController.loadStoryboard("ModalAlert")

Cargará tanto el Storyboardy UIViewControllercomo vcserá de tipo ModalAlertViewController. Nota Se supone que la ID del guión gráfico del guión gráfico tiene el mismo nombre que el guión gráfico y que el guión gráfico se ha marcado como Controlador de vista inicial .

extension UIViewController {
    /// Loads a `UIViewController` of type `T` with storyboard. Assumes that the storyboards Storyboard ID has the same name as the storyboard and that the storyboard has been marked as Is Initial View Controller.
    /// - Parameter storyboardName: Name of the storyboard without .xib/nib suffix.
    static func loadStoryboard<T: UIViewController>(_ storyboardName: String) -> T? {
        let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
        if let vc = storyboard.instantiateViewController(withIdentifier: storyboardName) as? T {
            vc.loadViewIfNeeded() // ensures vc.view is loaded before returning
            return vc
        }
        return nil
    }
}
normando
fuente