Jak mogę załadować planszę programowo z klasy?

183

Mój problem polega na tym, że szukałem sposobu na użycie zarówno scenorysów, jak i Xib . Ale nie mogę znaleźć odpowiedniego sposobu na programowe ładowanie i wyświetlanie scenorysu. Projekt zaczął się rozwijać w Xib, a teraz bardzo trudno jest zagnieździć wszystkie pliki Xib w scenorysie. Szukałem więc sposobu na zrobienie tego w kodzie, tak jak w alloc, init, pushprzypadku viewControllers. W moim przypadku mam tylko jeden kontroler w serii ujęć: UITableViewControllerktóry ma statyczne komórki z pewną zawartością, którą chcę pokazać. Jeśli ktoś zna właściwy sposób pracy zarówno z Xibem, jak i Storyboard bez wielkiego refaktoryzacji, będę wdzięczny za wszelką pomoc.

kokoko
źródło

Odpowiedzi:

370

W swoim scenorysie przejdź do Inspektora atrybutów i ustaw identyfikator kontrolera widoku. Następnie możesz przedstawić ten kontroler widoku za pomocą następującego kodu.

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"myViewController"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
James Beith
źródło
65
[sb instantiateInitialViewController]jest przydatny, jeśli chcesz uruchomić na domyślnym kontrolerze sceny.
zwrócił uwagę
James, dziękuję! Od dłuższego czasu próbuję wymyślić, jak utworzyć instancję widoku Storyboard. Twoja odpowiedź (i pytanie kokoko) jest najbardziej odświeżająca.
bejonbee
W kodzie Jamesa Beitha należy ponownie użyć tego UIViewControler * vc, jeśli jest on przełączany w tę iz powrotem z bieżącym kontrolerem widoku. Dowiedziałem się, w jaki sposób vc trzyma się i jest podłączony do końcówki scenorysu, dopóki użytkownik nie naciśnie przycisku w nowym widoku, a teraz jest wyciek pamięci z tym odrzuconym vc z poprzednich inkantacji tego kodu.
SWoo
11
Jeśli ktoś chce wiedzieć, jak to zrobić w delegacie aplikacji, zamień [self presentViewcontroller]logikę na te wiersze w następującej kolejności: 1) self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];2) self.window.rootViewController = vc;i 3) [self.window makeKeyAndVisible];. Prawdopodobnie możesz również pozbyć się modalTransitionStylelinii, ponieważ nie jest to modalne przejście z delegata aplikacji.
lewiguez
Do Twojej wiadomości, jeśli chcesz „wypchnąć” nową scenoryskę zamiast wyskakiwać modalnie, spójrz na odpowiedź chaithraVeeresh.
Adam Johns
76

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

Warunek wstępny

Przypisz identyfikator scenorysu do kontrolera widoku.

Identyfikator serii ujęć

IB> Pokaż inspektora tożsamości> Tożsamość> Identyfikator scenorysu

Swift (starsza wersja)

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

Edycja: Swift 2 zasugerowany w komentarzu Freda A.

jeśli chcesz korzystać bez nawigacji Sterownik musisz użyć w następujący sposób:

    let Storyboard  = UIStoryboard(name: "Main", bundle: nil)
    let vc = Storyboard.instantiateViewController(withIdentifier: "viewController")
    present(vc , animated: true , completion: nil)
SwiftArchitect
źródło
1
W Swift 2 nie trzeba dodawać „as? UIViewController”, kompilator określa to automatycznie
Frédéric Adda,
2
lub możesz po prostu zrobić self.storyboardi połączyć linię 1 i 2
Honey
17

W inspektorze atrybutów podaj identyfikator tego kontrolera widoku, a poniższy kod działa dla mnie

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
DetailViewController *detailViewController = [storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
[self.navigationController pushViewController:detailViewController animated:YES];
chaithraVeeresh
źródło
5

Spróbuj tego

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

[[UIApplication sharedApplication].keyWindow setRootViewController:vc];
Adetiloye Philip Kehinde
źródło
Użyj tego, jeśli nie używasz UINavigationController, jak pokazano w innych odpowiedziach
latenitecoder 10.09.17
2

w szybkim nawigatorze
NavigationController i pushController, który możesz zastąpić

present(vc, animated:true , completion: nil)
Tarik
źródło
1

W przypadku szybkich 3 i 4 możesz to zrobić. Dobrą praktyką jest ustawienie nazwy StoryboardID równej 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)
   }
}

a następnie możesz załadować Storyboard do ViewController w następujący sposób:

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

}

Podczas tworzenia nowej Storyboard po prostu ustaw tę samą nazwę na StoryboardID i dodaj nazwę Storyboard w wyliczeniu „ StoryBoardName

gandhi Mena
źródło
0

Zawsze możesz przejść bezpośrednio do kontrolera głównego:

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateInitialViewController];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
użytkownik938797
źródło
0

Poniższe rozszerzenie pozwala załadować plik Storyboardi jest on powiązany UIViewController. Przykład: jeśli masz UIViewControllernazwaną ModalAlertViewControlleri storyboard o nazwie „ModalAlert” np

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

Załaduje zarówno Storyboardi UIViewControlleri vcbędzie typu ModalAlertViewController. Uwaga Zakłada, że ​​identyfikator scenorysu ma taką samą nazwę jak scenorys i że scenariusz został oznaczony jako kontroler widoku początkowego .

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
    }
}
Norman
źródło