Como posso carregar o storyboard programaticamente da aula?

183

Meu problema é que eu estava procurando uma maneira de usar o storyboard e o xib . Mas não consigo encontrar uma maneira adequada de carregar e mostrar o storyboard programaticamente. O projeto foi iniciado com o xib e agora é muito difícil aninhar todos os arquivos xib no storyboard. Então, eu estava procurando uma maneira de fazer isso em código, como no alloc, init, pushviewControllers. No meu caso, tenho apenas um controlador no storyboard:, UITableViewControllerque possui células estáticas com algum conteúdo que quero mostrar. Se alguém souber a maneira correta de trabalhar tanto com o xib quanto com o storyboard sem grandes refatorações, agradecerei por qualquer ajuda.

kokoko
fonte

Respostas:

370

No seu storyboard, vá ao inspetor Attributes e defina o Identifier do controlador de exibição. Você pode apresentar esse controlador de exibição usando o código a seguir.

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"myViewController"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
James Beith
fonte
65
[sb instantiateInitialViewController]é útil se você deseja iniciar no controlador de exibição padrão da cena.
drewish
James, obrigado! Estou procurando há algum tempo tentando descobrir como instanciar a exibição de um Storyboard. Sua resposta (e a pergunta de kokoko) é mais refrescante de encontrar.
bejonbee
No código de James Beith, é preciso reutilizar esse UIViewControler * vc se ele for alternado com o atual controlador de exibição. Eu descobri da maneira mais difícil que o vc fica por perto e é conectado à ponta do storyboard até o usuário pressionar um botão na nova visualização, e agora há um vazamento de memória com o vc descartado dos encantamentos anteriores deste código.
SWoo
11
Caso alguém queira saber como fazer isso no delegado do aplicativo, substitua a [self presentViewcontroller]lógica por estas linhas na seguinte ordem: 1) self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];2) self.window.rootViewController = vc;e 3) [self.window makeKeyAndVisible];. Você também pode provavelmente se livrar da modalTransitionStylelinha, porque essa não é uma transição modal do delegado do aplicativo.
precisa saber é o seguinte
Para sua informação, se você quiser "empurrar" o novo storyboard em vez de aparecer modalmente, veja a resposta 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)

Pré-requisito

Atribua um ID do Storyboard ao seu controlador de exibição.

ID do storyboard

IB> Mostrar o inspetor de identidade> Identidade> ID do storyboard

Swift (legado)

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

Edit: Swift 2 sugerido em um comentário por Fred A.

se você deseja usar sem nenhum controlador de navegação, use o seguinte:

    let Storyboard  = UIStoryboard(name: "Main", bundle: nil)
    let vc = Storyboard.instantiateViewController(withIdentifier: "viewController")
    present(vc , animated: true , completion: nil)
SwiftArchitect
fonte
1
No Swift 2, você não precisa adicionar "as? UIViewController", o compilador determina automaticamente
Frédéric Adda
2
ou você pode simplesmente fazer self.storyboarde mesclar as linhas 1 e 2
Honey
17

No inspetor de atributos, forneça o identificador para esse controlador de exibição e o código abaixo funciona para mim

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

Tente isto

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

[[UIApplication sharedApplication].keyWindow setRootViewController:vc];
Adetiloye Philip Kehinde
fonte
Use isto se você não estiver usando um UINavigationController como mostrado em outras respostas
latenitecoder
2

no rápido
NavigationController e pushController, você pode substituir por

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

Nos swift 3 e 4 , você pode fazer isso. A boa prática é definir o nome do Storyboard igual ao 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)
   }
}

e então você pode carregar seu Storyboard no seu ViewController da seguinte maneira:

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)
     }

}

Ao criar um novo Storyboard, defina o mesmo nome no StoryboardID e adicione o nome do Storyboard na sua enumeração " StoryBoardName "

gandhi Mena
fonte
0

Você sempre pode pular direto para o controlador raiz:

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

A extensão abaixo permitirá que você carregue um Storyboarde está associado UIViewController. Exemplo: Se você tem um UIViewControllerchamado ModalAlertViewControllere um storyboard com o nome "ModalAlert" eg

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

Irá carregar tanto o Storyboarde UIViewControllere vcserá do tipo ModalAlertViewController. Nota Supõe que o ID do storyboard do storyboard tenha o mesmo nome que o storyboard e que o storyboard tenha sido marcado como É o controlador de exibição 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
fonte