问题
In iOS <= 7, directly after calling dismissViewControllerAnimated:completion:
would result in presentedViewController
being nil
.
In iOS 8, presentedViewController
still points to the presented viewcontroller, right until the completion block is executed.
[self dismissViewControllerAnimated:NO completion:^{
//self.presentedViewController is nil
}];
//self.presentedViewController is nil on iOS 7, but not nil on iOS 8
So in iOS 8 we cannot rely on the property presentedViewController
in order to find out which viewcontroller is currently the top visible viewcontroller.
In iOS 8, alerts need to be presented onto a viewcontroller (which poses another problem). They will not show if the viewcontroller we try to present on already presents a viewcontroller.
If I just dismissed my presented viewcontroller and show a UIAlertController
on the currently top visible viewcontroller (by recursively searching for the last presentedViewController
), then it will of course not show but log an error message: "Warning: Attempt to present on whose view is not in the window hierarchy!"
- Is this a bug in iOS 8 or just the new way?
- How can I find out the viewcontroller I can present my
UIALertController
on?
回答1:
I found a workaround to find out which viewcontroller I can present the alert upon:
@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];
Swift 3:
import UIKit
extension UIViewController {
func visibleViewController() -> UIViewController? {
guard !(self is UINavigationController) else {
let navVC = self as! UINavigationController
return navVC.topViewController?.visibleViewController()
}
guard !(self is UITabBarController) else {
let tabVC = self as! UITabBarController
return tabVC.selectedViewController?.visibleViewController()
}
if self.presentedViewController == nil ||
self.presentedViewController!.isBeingDismissed {
return self
}
return self.presentedViewController?.visibleViewController()
}
}
来源:https://stackoverflow.com/questions/26907411/dismissviewcontrolleranimatedcompletion-on-ios-8