Hot*_*cks 240 objective-c uiviewcontroller uikit uiview ios
我现在遇到了几个案例,它们可以方便地找到"最顶层"的视图控制器(负责当前视图的控制器),但还没有找到办法.
基本上挑战是这样的:假设一个人在一个不是视图控制器(或视图)的类中执行[并且没有活动视图的地址]并且还没有传递最顶层视图控制器的地址(或者说,导航控制器的地址),是否可以找到该视图控制器?(如果是这样,怎么样?)
或者,如果失败了,是否有可能找到最顶层的视图?
Eri*_*ric 417
我认为你需要一个接受的答案和@ fishstix的组合
+ (UIViewController*) topMostController
{
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
Run Code Online (Sandbox Code Playgroud)
Swift 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
}
Run Code Online (Sandbox Code Playgroud)
kle*_*leo 151
要完成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;
}
}
Run Code Online (Sandbox Code Playgroud)
Wil*_*ith 79
iOS 4在UIWindow上引入了rootViewController属性:
[UIApplication sharedApplication].keyWindow.rootViewController;
Run Code Online (Sandbox Code Playgroud)
您需要在创建视图控制器后自己设置它.
Yuc*_*ong 47
一个完整的非递归版本,负责不同的场景:
UINavigationControllerUITabBarControllerObjective-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;
}
}
Run Code Online (Sandbox Code Playgroud)
Swift 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
}
}
Run Code Online (Sandbox Code Playgroud)
Var*_*una 27
使用扩展获取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()
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
UIApplication.sharedApplication().keyWindow!.rootViewController!.topMostViewController()
Run Code Online (Sandbox Code Playgroud)
小智 24
为了完成Eric的答案(在浏览过程中遗漏了弹出窗口,导航控制器,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;
}
}
Run Code Online (Sandbox Code Playgroud)
================================================== ===================
现在你需要做的就是获得最顶层的视图控制器,调用上面的方法如下:
UIViewController *topMostViewControllerObj = [self topViewController];
Run Code Online (Sandbox Code Playgroud)
Awe*_*e-o 21
这个答案包括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;
}
Run Code Online (Sandbox Code Playgroud)
ipo*_*ima 13
我最近在我的一个项目中得到了这种情况,当网络状态发生变化时,需要显示控制器显示的通知视图以及类型(UINavigationController,经典控制器或自定义视图控制器).
所以我juste发布了我的代码,这很简单并且实际上基于协议,因此它对于每种类型的容器控制器都是灵活的.它似乎与最后的答案有关,但是以一种非常灵活的方式.
你可以在这里获取代码:PPTopMostController
并获得最高控制器使用
UIViewController *c = [UIViewController topMostController];
Run Code Online (Sandbox Code Playgroud)
Jon*_*asG 11
这是对Eric的回答的改进:
UIViewController *_topMostController(UIViewController *cont) {
UIViewController *topController = cont;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
if ([topController isKindOfClass:[UINavigationController class]]) {
UIViewController *visible = ((UINavigationController *)topController).visibleViewController;
if (visible) {
topController = visible;
}
}
return (topController != cont ? topController : nil);
}
UIViewController *topMostController() {
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *next = nil;
while ((next = _topMostController(topController)) != nil) {
topController = next;
}
return topController;
}
Run Code Online (Sandbox Code Playgroud)
_topMostController(UIViewController *cont) 是一个辅助函数.
现在您需要做的就是调用topMostController()并返回最顶层的UIViewController!
小智 8
- (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;
}
}
Run Code Online (Sandbox Code Playgroud)
UIApplication在Swift中的简单扩展:
注意:
它在乎的moreNavigationController内UITabBarController
extension UIApplication {
class func topViewController(baseViewController: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = baseViewController as? UINavigationController {
return topViewController(navigationController.visibleViewController)
}
if let tabBarViewController = baseViewController as? UITabBarController {
let moreNavigationController = tabBarViewController.moreNavigationController
if let topViewController = moreNavigationController.topViewController where topViewController.view.window != nil {
return topViewController(topViewController)
} else if let selectedViewController = tabBarViewController.selectedViewController {
return topViewController(selectedViewController)
}
}
if let splitViewController = baseViewController as? UISplitViewController where splitViewController.viewControllers.count == 1 {
return topViewController(splitViewController.viewControllers[0])
}
if let presentedViewController = baseViewController?.presentedViewController {
return topViewController(presentedViewController)
}
return baseViewController
}
}
Run Code Online (Sandbox Code Playgroud)
用法简单:
if let topViewController = UIApplication.topViewController() {
//do sth with top view controller
}
Run Code Online (Sandbox Code Playgroud)
@implementation UIWindow (Extensions)
- (UIViewController*) topMostController
{
UIViewController *topController = [self rootViewController];
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
@end
这是我对此的看法.感谢@Stakenborg指出了跳过让UIAlertView成为最顶级控制器的方法
-(UIWindow *) returnWindowWithWindowLevelNormal
{
NSArray *windows = [UIApplication sharedApplication].windows;
for(UIWindow *topWindow in windows)
{
if (topWindow.windowLevel == UIWindowLevelNormal)
return topWindow;
}
return [UIApplication sharedApplication].keyWindow;
}
-(UIViewController *) getTopMostController
{
UIWindow *topWindow = [UIApplication sharedApplication].keyWindow;
if (topWindow.windowLevel != UIWindowLevelNormal)
{
topWindow = [self returnWindowWithWindowLevelNormal];
}
UIViewController *topController = topWindow.rootViewController;
if(topController == nil)
{
topWindow = [UIApplication sharedApplication].delegate.window;
if (topWindow.windowLevel != UIWindowLevelNormal)
{
topWindow = [self returnWindowWithWindowLevelNormal];
}
topController = topWindow.rootViewController;
}
while(topController.presentedViewController)
{
topController = topController.presentedViewController;
}
if([topController isKindOfClass:[UINavigationController class]])
{
UINavigationController *nav = (UINavigationController*)topController;
topController = [nav.viewControllers lastObject];
while(topController.presentedViewController)
{
topController = topController.presentedViewController;
}
}
return topController;
}
Run Code Online (Sandbox Code Playgroud)
有关最新的Swift版本:
创建文件,请为其命名UIWindowExtension.swift并粘贴以下代码段:
import UIKit
public extension UIWindow {
public var visibleViewController: UIViewController? {
return UIWindow.getVisibleViewControllerFrom(self.rootViewController)
}
public static func getVisibleViewControllerFrom(vc: UIViewController?) -> UIViewController? {
if let nc = vc as? UINavigationController {
return UIWindow.getVisibleViewControllerFrom(nc.visibleViewController)
} else if let tc = vc as? UITabBarController {
return UIWindow.getVisibleViewControllerFrom(tc.selectedViewController)
} else {
if let pvc = vc?.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(pvc)
} else {
return vc
}
}
}
}
func getTopViewController() -> UIViewController? {
let appDelegate = UIApplication.sharedApplication().delegate
if let window = appDelegate!.window {
return window?.visibleViewController
}
return nil
}
Run Code Online (Sandbox Code Playgroud)
在任何地方使用它:
if let topVC = getTopViewController() {
}
Run Code Online (Sandbox Code Playgroud)
extension UIApplication {
class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topViewController(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topViewController(controller: presented)
}
return controller
}
}
Run Code Online (Sandbox Code Playgroud)
从任何地方使用它,例如,
UIApplication.topViewController()?.present(yourController, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)
或者像,
UIApplication.topViewController()?
.navigationController?
.popToViewController(yourController,
animated: true)
Run Code Online (Sandbox Code Playgroud)
适合任何类,如 UINavigationController、UITabBarController
享受!
Swift 4.2 中简洁而全面的解决方案,考虑了UINavigationControllers、UITabBarControllers、呈现和子视图控制器:
extension UIViewController {
func topmostViewController() -> UIViewController {
if let navigationVC = self as? UINavigationController,
let topVC = navigationVC.topViewController {
return topVC.topmostViewController()
}
if let tabBarVC = self as? UITabBarController,
let selectedVC = tabBarVC.selectedViewController {
return selectedVC.topmostViewController()
}
if let presentedVC = presentedViewController {
return presentedVC.topmostViewController()
}
if let childVC = children.last {
return childVC.topmostViewController()
}
return self
}
}
extension UIApplication {
func topmostViewController() -> UIViewController? {
return keyWindow?.rootViewController?.topmostViewController()
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
let viewController = UIApplication.shared.topmostViewController()
Run Code Online (Sandbox Code Playgroud)
使用以下扩展名抓取当前可见的UIViewController。适用于Swift 4.0及更高版本
extension UIApplication {
class func topViewController(_ viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = viewController as? UINavigationController {
return topViewController(nav.visibleViewController)
}
if let tab = viewController as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(selected)
}
}
if let presented = viewController?.presentedViewController {
return topViewController(presented)
}
return viewController
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用?
let objViewcontroller = UIApplication.topViewController()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
183653 次 |
| 最近记录: |