[英]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.