2014-10-17 85 views
6

傳統UIAlertView與新UIAlertController之間的區別在於後者需要通過presentViewController:animated:completion:呈現在特定視圖控制器中。這對我的用例提出了一個尷尬的問題:如果第二個視圖控制器出現時(例如由於網絡連接失敗導致的錯誤對話),已經顯示UIAlertController(例如評級對話框)會怎麼樣。我經歷過這種情況,第二個UIAlertController只是不顯示。如果已顯示警報,則顯示UIAlertController

編輯:目前我試圖顯示一個提醒,我不知道目前是否有任何提示。

你如何應對這種情況?

+0

[此線索] [1]講解如何正確解決類似問題 [1]:http://stackoverflow.com/questions/21179922/can-i-check-if- any-uialertview-displays-right-now – 2014-11-18 06:05:23

+0

其他線程中的解決方案非常脆弱和難看,並且可能會在iOS8中破解。 – fabb 2014-11-23 09:31:52

回答

4

我找到了一個解決辦法,找出其中的viewController我能呈現警惕。我還張貼了答案here

@implementation UIViewController (visibleViewController) 

- (UIViewController *)my_visibleViewController { 

    if ([self isKindOfClass:[UINavigationController class]]) { 
     // do not use method visibleViewController as the presentedViewController could beingDismissed 
     return [[(UINavigationController *)self topViewController] my_visibleViewController]; 
    } 

    if ([self isKindOfClass:[UITabBarController class]]) { 
     return [[(UITabBarController *)self selectedViewController] my_visibleViewController]; 
    } 

    if (self.presentedViewController == nil || self.presentedViewController.isBeingDismissed) { 
     return self; 
    } 

    return [self.presentedViewController my_visibleViewController]; 
} 

@end 

// To show a UIAlertController, present on the following viewcontroller: 
UIViewController *visibleViewController = [[UIApplication sharedApplication].delegate.window.rootViewController my_visibleViewController]; 
3

由於UIAlertControllor本身就是一個UIViewController,您可以通過從現有的介紹提出的第一個頂部的第二UIAlertController:

alertController.PresentViewController(alertController2, animated: true, completionHandler: null); 
+0

問題是,人們必須首先找出頂級的視圖控制器。假設我不知道是否有amy警報或其他呈現的視圖控制器顯示。 – fabb 2014-11-16 07:55:59

+0

使用這個讓高層視圖控制器: \t私人的UIViewController GetTopPresentedViewController() \t { \t \t的UIViewController currentVC =此。的viewController; \t \t而(真) \t \t { \t \t \t的UIViewController nextVC = currentVC.PresentedViewController; \t \t \t如果(nextVC == NULL) \t \t \t { \t \t \t \t返回currentVC; \t \t \t} \t \t \t \t currentVC = nextVC; \t \t \t} \t \t} – Bbx 2014-11-17 11:03:00

+0

看到我的回答 - 不要忘記'isBeingDismissed'標誌。 – fabb 2014-11-17 11:53:47

0

此代碼實現當應用程序有可能存在對窗口和當前之前的一些警告要求其檢查,如果有任何其他AlertController呈現則已,如果給出則提出警告上Alertcontroller出現在窗口中。

以下是另一種選擇,您可以根據您的要求進行優化。

 func showAlert(message:String) { 

     if let alert = self.checkIfAlertViewHasPresented() { 
      alert.presentViewController(alertController, animated: true, completion: nil) 

     } else { 
      self.window?.rootViewController!.presentViewController(alertController, animated: true, completion: nil) 
     } 
    } 

    func checkIfAlertViewHasPresented() -> UIAlertController? { 

     if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController { 
      while let presentedViewController = topController.presentedViewController { 
       topController = presentedViewController 
      } 
      if topController is UIAlertController { 
       return (topController as! UIAlertController) 
      } else { 
       return nil 
      } 
     } 
     return nil 
    } 
+0

這不包括接受答案中涵蓋的一些特殊情況。 – fabb 2016-10-12 08:41:10

+0

@fabb同意你的意見。在編寫關於由代碼塊完成的條件的代碼之前,我已經說過了。如果一些新手開發人員有理解其他複雜條件的問題,我認爲我的答案是次要選擇。 – iDevAmit 2016-10-12 08:45:19

+0

恕我直言,特別是新手應該被教導做正確的事情,沒有進攻 – fabb 2016-10-12 08:47:26

0

這就是我正在使用的。這種方式如果警報已經顯示, 我更喜歡用戶解僱它而不是應用程序。 因此,視圖已經呈現警戒,我只需等待5秒鐘,然後再試一次。我只是想補充一點,我沒有太多的測試,但它工作。(從我做的1個測試),所以我希望我不會錯過任何東西,因爲我很長時間以來一直在想這個問題,而這個解決方案的聲音太容易:)

-(void) alertUserWithTitle:(NSString*) title Message:(NSString*) message 
{ 
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:title                    message:message 
                      preferredStyle:UIAlertControllerStyleAlert]; 

        UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault 
                      handler:^(UIAlertAction * action) {}]; 

        [alert addAction:defaultAction]; 

        if(self.presentedViewController == nil) 
        { 
         [self presentViewController:alert animated:YES completion:nil]; 
        }else 
        { 
         double delayInSeconds = 2.0; 
         dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 

         dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 

          [self alertUserWithTitle:title Message:message]; 

         }); 

        } 
} 
+0

適合某些用例。如果警報阻止進一步的用戶交互,則不太理想。 – fabb 2016-12-14 21:52:15

0

這裏有一個解決方案,我在斯威夫特3.使用這是顯示警告給用戶的功能,如果你把它多次用戶已經駁回了警報之前,它會將新的警報文本添加到已顯示的警報中。如果顯示其他視圖,則不會顯示警報。並非所有人都會同意這種行爲,但對於簡單的情況,這種方式很有效。

extension UIViewController { 
    func showAlert(_ msg: String, title: String = "") { 
     if let currentAlert = self.presentedViewController as? UIAlertController { 
      currentAlert.message = (currentAlert.message ?? "") + "\n\nUpdate:\(title): \(msg)" 
      return 
     } 

     // create the alert 
     let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert) 
     alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) 

     // show the alert 
     self.present(alert, animated: true, completion: nil) 
    } 
}