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
,这就是为什么 window
的 rootViewController
根据情节提要是 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
}
}
现在您需要从 window
的 rootViewController
获取 visiableViewController
并在 viewController 上显示您的 alertView。
let visiableViewController = UIApplication.visibleViewController(rootViewController)
visiableViewController.presentViewController(alertController, animated: true, completion: nil)
我正在尝试设置我的应用程序以支持推送通知,当应用程序从推送通知打开时,我的一切正常,但现在我正在尝试添加以在应用程序打开时显示警报并收到通知。
到目前为止,我的 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)
}
}
要了解应用程序故事板的构建方式,请参阅
代码运行时,我在控制台中收到以下日志:
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
,这就是为什么 window
的 rootViewController
根据情节提要是 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
}
}
现在您需要从 window
的 rootViewController
获取 visiableViewController
并在 viewController 上显示您的 alertView。
let visiableViewController = UIApplication.visibleViewController(rootViewController)
visiableViewController.presentViewController(alertController, animated: true, completion: nil)