2012-04-23 19 views
20

Buduję aplikację klienta WWW 5.1 IOS, która korzysta z storyboardu. Jednym z moich działań jest "wylogowanie", podczas którego chcę zresetować mój widok główny do początkowego widoku utworzonego przez widok główny Storyboard. (Po zalogowaniu niektóre elementy widoku są usuwane lub dodawane na podstawie tego, kim jesteś, po wylogowaniu chcę zresetować je do wartości domyślnych, które określiłem w scenorysie.)Resetowanie scenorysu na wylogowaniu

Zdaję sobie sprawę że mogę programowo zresetować/ponownie dodać wszystkie elementy, ale co to jest storyboard? Sądzę, że musi istnieć sposób na powrót do pierwszej wersji poprzez ponowne załadowanie pliku widoku, prawda?

+0

Czy kiedykolwiek to wymyśliłeś? Mam dokładnie taką samą potrzebę ... –

Odpowiedz

28

Znalazłem następujące podejście działa dla mnie. Należy pamiętać, że używam ARC, nie wiedząc, czy ma to jednak duży wpływ na rozwiązanie. Po pierwsze, w klasie delegata aplikacji w application:didFinishLaunchingWithOptions: przechwycić do inital Storyboard wystąpienie w następnej linii kodu:

_initalStoryboard = self.window.rootViewController.storyboard; 

(Oczywiście nie jest to przykład zmienna UIStoryboard* _initalStoryboard;)

Następnie następujących funkcji zdefiniowano w moim app delegata:

- (void)resetWindowToInitialView 
{ 
    for (UIView* view in self.window.subviews) 
    { 
     [view removeFromSuperview]; 
    } 

    UIViewController* initialScene = [_initalStoryboard instantiateInitialViewController]; 
    self.window.rootViewController = initialScene; 
} 

Uwaga: w pętli, która usuwa wszystkie subviews z window. Dokumentacja UIWindow rootViewController stwierdza:

Jeśli okno ma istniejącego widoku hierarchii, stare poglądy są usunięte przed zainstalowaniem nowych.

Jednak nie znalazłem, aby tak było ... więc samodzielnie usuwam istniejące widoki przed przypisaniem nowego kontrolera rootViewController. Nie znalazłem żadnych niepokojących efektów ubocznych ani wycieków pamięci przy użyciu tej metody. Nie jestem bynajmniej ekspertem od magii UIKit, więc proponuję test testowy i przetestować to rozwiązanie, jeśli planujesz użyć go samemu. Cheers

+0

Chciałem to wypróbować, ale tak naprawdę nie pokazać, w jaki sposób wywołać funkcję z kontrolera po naciśnięciu przycisku. – gdubs

+2

Sprawdź to pytanie SO: http://stackoverflow.com/questions/1184146/getting-a-reference-to-the-uiaplikacja-delegate Pokazuje, jak możesz uzyskać odwołanie do delegata aplikacji - w twoim przypadku użyjesz tego w kontrolerze widoku sceny. Tak więc w przycisku obsługi dotykowej przycisku znajduje się coś takiego: MyApplicationDelegate * appDelegate = (MyApplicationDelegate *) [delegat UIApplication sharedApplication]]; [appDelegate resetWindowToInitialView]; –

+2

dzięki szefowi .... – gdubs

1

następujące prace wielki dla mnie, jeśli używasz struktury NavController opartego:

UIWindow *window = [[UIApplication sharedApplication].windows firstObject]; 
UINavigationController *navController = (UINavigationController *)window.rootViewController; 
UIViewController *vc = [navController.storyboard instantiateViewControllerWithIdentifier:@"Login"]; 
navController.viewControllers = @[vc]; 

Musisz przypisać Storyboard ID "Login" do loginu VC, aby to zadziałało.

0

Poniższe działa na mnie, jeśli mogę użyć UISplitViewController opartych strukturę (testowane na iOS 8+):

Usuń Storyboard z projektów Ogólne ->Wdrożenie Information, więc rozwijana wygląda poniżej i musisz skonfigurować scenorys w kodzie.

Deployment Info Empty Main Interface

Gdzieś w AppDelegate.m

- (void)setupViewControllers 
{ 
    // check for thread, as this method might be called by other (e.g. logout) logic 
    if ([NSThread currentThread] != [NSThread mainThread]) { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self setupViewControllers]; 
     }); 
     return; 
    } 

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; 
    UIViewController *vc =[storyboard instantiateInitialViewController]; 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    self.window.rootViewController = vc; 

    // configure split vc 
    // Note: I reference split vc for my own purpose, but it is your mater of choice 
    self.splitViewController = (UISplitViewController *)self.window.rootViewController; 
    self.splitViewController.delegate = self; 
    self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible; 
    self.splitViewController.preferredPrimaryColumnWidthFraction = 0.5; 

    [self.window makeKeyAndVisible]; 
} 

Aby uniknąć duplikatów kod, wywołać tę funkcję od application:didFinishLaunchingWithOptions: jako pierwszej konfiguracji

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    // some code... 
    [self setupViewControllers]; 
    // Optional: add splash view (e.g. [self addSplashView];) 
    // some code... 
} 

Wewnątrz kontrolera widoku jesteś gotowy zaprezentuj interfejs użytkownika użytkownikowi, usuń widok powitalny.Na przykład (w Swift):

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

    if !AppSession.currentSession().isLoggedIn() { 
     presentLoginViewController(false, completion: {()->Void in 
      self.removeSplash() 
     }) 
    } 
    else { 
     removeSplash() 
    } 

    // some code... 
} 

private func removeSplash() { 
    if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate { 
     appDelegate.removeSplashView() 
    } 
}