지금은 “최상위”뷰 컨트롤러 (현재 뷰를 담당하는 컨트롤러)를 찾는 것이 편리한 몇 가지 사례를 겪었지만 그 방법을 찾지 못했습니다.
기본적으로 문제는 다음과 같습니다. 뷰 컨트롤러 (또는 뷰) 가 아닌 (활성 뷰의 주소가없는 ) 클래스에서 실행 중이고 최상위 뷰 컨트롤러의 주소가 전달되지 않은 경우 ( 또는 네비게이션 컨트롤러의 주소), 해당 뷰 컨트롤러를 찾을 수 있습니까? (그렇다면 어떻게?)
아니면 실패하면 최상위 뷰를 찾을 수 있습니까?
답변
iOS 4는 UIWindow에 rootViewController 속성을 도입했습니다.
[UIApplication sharedApplication].keyWindow.rootViewController;
뷰 컨트롤러를 생성 한 후에 직접 설정해야합니다.
답변
허용 된 답변과 @fishstix의 조합이 필요하다고 생각합니다.
+ (UIViewController*) topMostController
{
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
스위프트 3.0+
func topMostController() -> UIViewController? {
guard let window = UIApplication.shared.keyWindow, let rootViewController = window.rootViewController else {
return nil
}
var topController = rootViewController
while let newTopController = topController.presentedViewController {
topController = newTopController
}
return topController
}
답변
JonasG를 완료하려면 답변 (탐색하는 동안 탭 막대 컨트롤러를 생략 한 사람) 현재 보이는 뷰 컨트롤러를 반환하는 내 버전이 있습니다.
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
답변
다른 시나리오를 처리하는 완전한 비 재귀 버전 :
- 뷰 컨트롤러가 다른 뷰를 제시하고 있습니다
- 뷰 컨트롤러는
UINavigationController
- 뷰 컨트롤러는
UITabBarController
목표 -C
UIViewController *topViewController = self.window.rootViewController;
while (true)
{
if (topViewController.presentedViewController) {
topViewController = topViewController.presentedViewController;
} else if ([topViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *nav = (UINavigationController *)topViewController;
topViewController = nav.topViewController;
} else if ([topViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tab = (UITabBarController *)topViewController;
topViewController = tab.selectedViewController;
} else {
break;
}
}
스위프트 4+
extension UIWindow {
func topViewController() -> UIViewController? {
var top = self.rootViewController
while true {
if let presented = top?.presentedViewController {
top = presented
} else if let nav = top as? UINavigationController {
top = nav.visibleViewController
} else if let tab = top as? UITabBarController {
top = tab.selectedViewController
} else {
break
}
}
return top
}
}
답변
확장 기능을 사용하여 Swift 용 최상위 컨트롤러 얻기
암호:
extension UIViewController {
@objc func topMostViewController() -> UIViewController {
// Handling Modal views
if let presentedViewController = self.presentedViewController {
return presentedViewController.topMostViewController()
}
// Handling UIViewController's added as subviews to some other views.
else {
for view in self.view.subviews
{
// Key property which most of us are unaware of / rarely use.
if let subViewController = view.next {
if subViewController is UIViewController {
let viewController = subViewController as! UIViewController
return viewController.topMostViewController()
}
}
}
return self
}
}
}
extension UITabBarController {
override func topMostViewController() -> UIViewController {
return self.selectedViewController!.topMostViewController()
}
}
extension UINavigationController {
override func topMostViewController() -> UIViewController {
return self.visibleViewController!.topMostViewController()
}
}
용법:
UIApplication.sharedApplication().keyWindow!.rootViewController!.topMostViewController()
답변
에릭의 답변 을 완성하려면 (팝 오버, 탐색 컨트롤러, tabbarcontrollers, 트래버스 중에 다른 뷰 컨트롤러에 하위 뷰로 추가 된 뷰 컨트롤러 제외) 현재 보이는 뷰 컨트롤러를 반환하는 내 버전이 있습니다.
===================================================== ====================
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)viewController {
if ([viewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)viewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([viewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navContObj = (UINavigationController*)viewController;
return [self topViewControllerWithRootViewController:navContObj.visibleViewController];
} else if (viewController.presentedViewController && !viewController.presentedViewController.isBeingDismissed) {
UIViewController* presentedViewController = viewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
}
else {
for (UIView *view in [viewController.view subviews])
{
id subViewController = [view nextResponder];
if ( subViewController && [subViewController isKindOfClass:[UIViewController class]])
{
if ([(UIViewController *)subViewController presentedViewController] && ![subViewController presentedViewController].isBeingDismissed) {
return [self topViewControllerWithRootViewController:[(UIViewController *)subViewController presentedViewController]];
}
}
}
return viewController;
}
}
===================================================== ====================
이제 가장 많은 뷰 컨트롤러를 얻으려면 다음과 같이 위의 메소드를 호출하면됩니다.
UIViewController *topMostViewControllerObj = [self topViewController];
답변
이 답변은 childViewControllers
깨끗하고 읽기 쉬운 구현을 포함 하고 유지합니다.
+ (UIViewController *)topViewController
{
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
return [rootViewController topVisibleViewController];
}
- (UIViewController *)topVisibleViewController
{
if ([self isKindOfClass:[UITabBarController class]])
{
UITabBarController *tabBarController = (UITabBarController *)self;
return [tabBarController.selectedViewController topVisibleViewController];
}
else if ([self isKindOfClass:[UINavigationController class]])
{
UINavigationController *navigationController = (UINavigationController *)self;
return [navigationController.visibleViewController topVisibleViewController];
}
else if (self.presentedViewController)
{
return [self.presentedViewController topVisibleViewController];
}
else if (self.childViewControllers.count > 0)
{
return [self.childViewControllers.lastObject topVisibleViewController];
}
return self;
}