簡體   English   中英

iOS:從任何地方返回到根視圖控制器

[英]iOS: return to root view controller from anywhere

我正在編寫一個需要服務器登錄的iPhone應用程序。 應用程序的根視圖控制器檢查用戶是否已登錄,並有條件地將用戶引導到兩個情節提要(登錄或主應用程序)之一。 根控制器不是UINavigationController(我見過的許多解決此問題的解決方案都假定是)。 如果用戶在服務器上注銷(超時等),服務器請求將返回HTTP 401,我在我的Web請求代碼中攔截了該HTTP 401 ...如何使用戶退回登錄屏幕和/或根視圖控制器? 我已經搜索了StackOverflow和互聯網的其余部分達數小時之久,但找不到答案。 我嘗試了Unwind Segue,它似乎被正確調用(沒有錯誤),但實際上並沒有展開到root視圖控制器,可能是因為我直接在root view controller上調用了它我的網絡請求類別中只有一個可見。 有什么想法嗎?

這是我的應用程序流程:

+-------------------+                                                      
+-------------------------->                   |                                                      
|                          |RootViewController |                                                      
|               +----------+UIViewController   +------+                                               
|               |          +-------------------+      |                                               
|               |                                     |                                               
|       +-------v---------+                 +----+----v-----------------+                             
|       |Login storyboard |                 |SWRevealViewController     |                             
|       |2 Views          |                 |see note                   |                             
|       +-------+---------+                 +---+-------------------+---+                             
|               |                               |                   |                                 
|               |                               |                   |                                 
+---------------+                    +----------v-------+      +----v--------------------------------+
                                     | Drawer           |      |  Main Storyboard                    |
                                     | UIViewController |      |  Starts with UINavigationController |
                                     +------------------+      |                                     |
                                                               +-------------------------------------+

SWRevealViewController是一種奇怪的野獸……它同時顯示兩個UIViewController,一個在另一個的前面, 而后一個則充當“抽屜”的角色,因此可以將前一個滑動到一邊以訪問它。

在RootViewController viewDidLoad ,訂閱注銷通知。 viewDidAppear中的同一類中,檢查用戶的登錄狀態。 如果用戶需要登錄, presentViewController在LoginViewController上顯示presentViewController,否則請顯示SWRevealController。

在您的通知處理程序中,如果用戶丟失了登錄狀態,請執行以下操作:

[self dismissViewControllerAnimated:YES];

當在根vc(自身)上調用Dismiss時,它並不關心頂部的視圖控制器是什么,或者兩者之間有多少視圖控制器,它會刪除所有內容以顯示被調用的vc。 該根vc將具有您的viewDidAppear **火,您可以將其構建為根據登錄狀態執行正確的操作。

在登錄視圖控制器中,您可以使用本地通知中心添加偵聽器

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDidLogout:) name:@"UserDidLogoutNotificationName" object:nil];

在通知所引用的方法中,關閉視圖控制器。

-(void)userDidLogout {
    [self dismissViewControllerAnimated:YES completion:nil];
 }

每當您要注銷時,只需撥打電話,就應該彈出到注銷屏幕

[[NSNotificationCenter defaultCenter]postNotification:@"UserDidLogoutNotificationName"]

根據您的圖表,我不會考慮返回注銷屏幕,而是彈出所有視圖控制器,直到顯示出來為止

正如我在對danh的回答評論指出的那樣 ,我可能遺漏了重要的細節。 我將登錄屏幕和主屏幕顯示為根視圖控制器的子視圖控制器。 經過一會兒的思考,我意識到解決方案是交換子視圖控制器。 隨后進行了許多研究和咬牙切齒,我得出了一個似乎可靠工作的解決方案。

首先,我從根視圖控制器的viewDidLoad顯示一個屏幕(這里是主屏幕),如下所示:

[self addChildViewController:self.mainViewController];
[self.view addSubview:self.mainViewController.view];
[self.mainViewController didMoveToParentViewController:self];
[self.view layoutIfNeeded];

然后,當我想切換到登錄屏幕時,請執行以下操作:

- (void)switchToLoginScreen
{
    [self switchScreensFrom:self.mainViewController to:self.loginViewController];
}

- (void)switchScreensFrom:(UIViewController *)fromViewController to:(UIViewController *)toViewController
{
    [fromViewController willMoveToParentViewController:nil];
    [self addChildViewController:toViewController];

    [self transitionFromViewController:fromViewController
                      toViewController:toViewController
                              duration:0.25
                               options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve
                            animations:^{}
                            completion:^(BOOL finished){
                                [fromViewController removeFromParentViewController];
                                [toViewController didMoveToParentViewController:self];
                            }];
}

過渡的另一種方式也類似。 從我的應用程序委托中的處理程序調用switchToLoginScreen方法,該方法可以通過self.window.rootViewController訪問根視圖控制器。 應用程序委托在應用程序啟動時將自己注冊為HTTP 401處理程序的委托。 謝謝danh; 雖然您的答案並不能直接解決我的問題,但確實讓我以一種新的方式思考問題,這使我找到了答案!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM