iOS项目开发中,经常会遇到需要知道应用正在显示哪个控制器的情况。比如,当收到一条推送通知时,要根据不同界面处理不同的业务逻辑,就需要知道收到通知时应用正处于哪个界面,即获取到应用正在显示的控制器。下面介绍一种方法,分别用swift和OC实现。
swift版:
func getCurrentVC() -> UIViewController? {
for window in UIApplication.shared.windows.reversed() {
var tempView: UIView? = window.subviews.last
for subview in window.subviews.reversed() {
if subview.classForCoder == NSClassFromString("UILayoutContainerView") {
tempView = subview
break
}
}
var nextResponder = tempView?.next
var next: Bool {
return !(nextResponder is UIViewController) || nextResponder is UINavigationController || nextResponder is UITabBarController || nextResponder?.classForCoder == NSClassFromString("UIInputWindowController")
}
while next{
tempView = tempView?.subviews.first
if tempView == nil {
return nil
}
nextResponder = tempView!.next
}
if let currentVC = nextResponder as? UIViewController {
return currentVC
}
}
return nil
}
OC版:
- (UIViewController *)getCurrentVC {
for (UIWindow *window in [UIApplication sharedApplication].windows.reverseObjectEnumerator) {
UIView *tempView = window.subviews.lastObject;
for (UIView *subview in window.subviews.reverseObjectEnumerator) {
if ([subview isKindOfClass:NSClassFromString(@"UILayoutContainerView")]) {
tempView = subview;
break;
}
}
BOOL(^canNext)(UIResponder *) = ^(UIResponder *responder){
if (![responder isKindOfClass:[UIViewController class]]) {
return YES;
} else if ([responder isKindOfClass:[UINavigationController class]]) {
return YES;
} else if ([responder isKindOfClass:[UITabBarController class]]) {
return YES;
} else if ([responder isKindOfClass:NSClassFromString(@"UIInputWindowController")]) {
return YES;
}
return NO;
};
UIResponder *nextResponder = tempView.nextResponder;
while (canNext(nextResponder)) {
tempView = tempView.subviews.firstObject;
if (!tempView) {
return nil;
}
nextResponder = tempView.nextResponder;
}
UIViewController *currentVC = (UIViewController *)nextResponder;
if (currentVC) {
return currentVC;
}
}
return nil;
}
使用该方法的需要注意的地方是,需要等到控制器viewDidAppear之后才能获取到正确的控制器