window.rootViewController 不是当前视图控制器

window.rootViewController is not the current view controller

我正在尝试设置我的应用程序以支持推送通知,当应用程序从推送通知打开时,我的一切正常,但现在我正在尝试添加以在应用程序打开时显示警报并收到通知。

到目前为止,我的 AppDelegate 中有以下代码:

  func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    println("Received alert and opened it")
    debugPrintln(userInfo)
    if let tripId = (userInfo["trip"] as? String)?.toInt() {
      if application.applicationState == UIApplicationState.Active { // App in foreground
        openTripFromForeground(tripId, type: userInfo["type"] as! String)
      } else { // App in background
        openTripFromBackground(tripId, type: userInfo["type"] as! String)
      }
    }
  }

  func openTripFromForeground(tripId: Int, type: String) {
    var alertController: UIAlertController!
    switch(type) {
      case "new":
        alertController = UIAlertController(title: "New trip", message: "You've been assigned to trip \(tripId).", preferredStyle: .Alert)
      case "changed":
        alertController = UIAlertController(title: "Changed trip", message: "Trip \(tripId) has changed.", preferredStyle: .Alert)
      case "removed":
        alertController = UIAlertController(title: "Removed from trip", message: "Trip \(tripId) has been removed.", preferredStyle: .Alert)
      default:
        println("Trip did something")
        return
    }
    if let rootViewController = self.window?.rootViewController {
      debugPrintln(rootViewController)
      rootViewController.presentViewController(alertController, animated: true, completion: nil)
    }
  }

要了解应用程序故事板的构建方式,请参阅 and this screenshot

代码运行时,我在控制台中收到以下日志:

2015-09-04 13:57:05.878 GoDriver[1050:415300] Warning: Attempt to present <UIAlertController: 0x14f76130> on <GoDriver.LoginViewController: 0x14e37fd0> whose view is not in the window hierarchy!

即使可见视图是 TripsTableViewController。

我们在应用委托中做了类似的事情,

BOOL viewLoaded = navController.topViewController.isViewLoaded;
            if (viewLoaded)
            {
                [navController presentViewController:yourViewController animated:YES completion:nil];
            }
            else
            {
                self.showDeepLink = true;
            }

然后主要activity

if (delegate.showDeepLink)
    {
        delegate.showDeepLink = false;
        [self.navigationController presentViewController:yourViewController animated:YES completion:nil];
    }

我已经使用这样的代码来对当前位于最顶层的任何控制器发出警报。也许类似的东西对你有用?

- (void)handleError:(NSError *)error {
    NSBundle *mainBundle = [NSBundle mainBundle];

    NSString *title = [error localizedDescription];
    NSString *message = [[error userInfo] objectForKey:NSLocalizedFailureReasonErrorKey];

    // Find top-most controller
    UIViewController *viewController = [_window rootViewController];

    UIViewController *presentedViewController;
    do {
        presentedViewController = [viewController presentedViewController];

        if (presentedViewController != nil) {
            viewController = presentedViewController;
        }
    } while (presentedViewController != nil);

    // Display alert
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message  preferredStyle:UIAlertControllerStyleAlert];

    [alertController addAction:[UIAlertAction actionWithTitle:[mainBundle localizedStringForKey:@"application.ok"] style:UIAlertActionStyleDefault handler:nil]];

    [viewController presentViewController:alertController animated:true completion:nil];
}

您似乎在 LoginViewController 之上呈现了 UINavigationController,这就是为什么 windowrootViewController 根据情节提要是 LoginViewController,它的视图是window 上未加载。

我在 UIApplication 上创建了扩展以获取 visiableViewControler

extension UIApplication {
    class func visibleViewController(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {

        if let nav = base as? UINavigationController {
            return visibleViewController(nav.visibleViewController)
        }

        if let tab = base as? UITabBarController {
            let moreNavigationController = tab.moreNavigationController

            if let top = moreNavigationController.topViewController where top.view.window != nil {
                return visibleViewController(top)
            } else if let selected = tab.selectedViewController {
                return visibleViewController(selected)
            }
        }

        if let presented = base?.presentedViewController {
            return visibleViewController(presented)
        }
        return base
    }
}

现在您需要从 windowrootViewController 获取 visiableViewController 并在 viewController 上显示您的 alertView。

let visiableViewController = UIApplication.visibleViewController(rootViewController)
visiableViewController.presentViewController(alertController, animated: true, completion: nil)