Come posso caricare lo storyboard a livello di codice dalla classe?


183

Il mio problema è che stavo cercando un modo per usare sia lo storyboard che xib . Ma non riesco a trovare il modo corretto di caricare e mostrare lo storyboard a livello di codice. Il progetto è stato avviato con xib e ora è molto difficile annidare tutti i file xib nello storyboard. Quindi stavo cercando un modo per farlo in codice, come con alloc, init, pushfor viewControllers. Nel mio caso ho solo un controller nello storyboard: UITableViewControllerche ha celle statiche con alcuni contenuti che voglio mostrare. Se qualcuno conosce il modo corretto di lavorare sia con Xib che con lo storyboard senza enormi refactoring, apprezzerò per qualsiasi aiuto.

Risposte:


370

Nello storyboard vai alla finestra di ispezione Attributi e imposta l'identificatore del controller di visualizzazione. È quindi possibile presentare quel controller di visualizzazione utilizzando il seguente codice.

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"myViewController"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];

65
[sb instantiateInitialViewController]è utile se si desidera avviare il controller di visualizzazione predefinito della scena.
Drewish

James, grazie! Ho cercato per un po 'di tempo cercando di capire come creare un'istanza della vista di Storyboard. La tua risposta (e la domanda di Kokoko) sono più interessanti da trovare.
Bejonbee,

Sul codice di James Beith, si deve riutilizzare quel UIViewControler * vc se è cambiato avanti e indietro con il viewcontroller corrente. Ho scoperto il modo in cui il vc si attacca e viene collegato al pennino dello storyboard fino a quando l'utente non preme un pulsante sulla nuova vista, e ora c'è una perdita di memoria con quel vc scartato dai precedenti incantesimi di questo codice.
SWoo

11
Nel caso in cui qualcuno desideri sapere come farlo nel delegato dell'app, sostituisci la [self presentViewcontroller]logica con queste righe nel seguente ordine: 1) self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];2) self.window.rootViewController = vc;e 3) [self.window makeKeyAndVisible];. Probabilmente puoi anche sbarazzarti della modalTransitionStylelinea perché questa non è una transizione modale dal delegato dell'app.
lewiguez,

Cordiali saluti, se vuoi "spingere" il nuovo storyboard invece di spuntare modalmente, guarda la risposta di 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)

necessario

Assegna un ID storyboard al controller della vista.

ID storyboard

IB> Mostra la finestra di ispezione Identità> Identità> ID storyboard

Swift (legacy)

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

Modifica: Swift 2 suggerito in un commento di Fred A.

se si desidera utilizzare senza alcun controller di navigazione, è necessario utilizzare come segue:

    let Storyboard  = UIStoryboard(name: "Main", bundle: nil)
    let vc = Storyboard.instantiateViewController(withIdentifier: "viewController")
    present(vc , animated: true , completion: nil)

1
In Swift 2, non è necessario aggiungere "as? UIViewController", il compilatore lo determina automaticamente
Frédéric Adda

2
oppure puoi semplicemente fare self.storyboarde unire line1 & 2
Honey

17

Nella finestra di ispezione degli attributi fornire l'identificatore per quel controller di visualizzazione e il codice seguente funziona per me

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

5

Prova questo

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

[[UIApplication sharedApplication].keyWindow setRootViewController:vc];

Usalo se non stai usando un UINavigationController come mostrato in altre risposte
latenitecoder

2

in Rapido
NavigationController e PushController è possibile sostituire

present(vc, animated:true , completion: nil)

1

Per Swift 3 e 4 , puoi farlo. La buona pratica è impostare il nome dello Storyboard uguale 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)
   }
}

e quindi puoi caricare lo Storyboard nel tuo ViewController in questo modo:

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

}

Quando crei un nuovo Storyboard, imposta lo stesso nome su StoryboardID e aggiungi il nome dello Storyboard nel tuo enum " StoryBoardName "


0

Puoi sempre saltare direttamente al controller di root:

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

0

L'estensione di seguito ti permetterà di caricare a Storyboarded è associata UIViewController. Esempio: se hai un UIViewControllernome ModalAlertViewControllere uno storyboard chiamato "ModalAlert" ad es

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

Caricherà sia Storyboarde UIViewControllerche vcsarà di tipo ModalAlertViewController. Nota Presuppone che l'ID storyboard dello storyboard abbia lo stesso nome dello storyboard e che lo storyboard sia stato contrassegnato come Is Initial View Controller .

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
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.