前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >iOS学习——获取当前最顶层的ViewController

iOS学习——获取当前最顶层的ViewController

作者头像
mukekeheart
发布于 2018-02-28 08:43:26
发布于 2018-02-28 08:43:26
6.7K00
代码可运行
举报
运行总次数:0
代码可运行

  在iOS开发过程中,我们经常性会需要获取当前页面的ViewController,然后利用ViewController进行一些操作,例如在最顶层的ViewController上展示一个UIAlertController,或者在最顶层的ViewController上present另一个ViewController,或者进行其他操作。

1 实现思路

  通过最底层的ViewController依次向上寻找,直到找到最顶层的ViewController,也就是从UIApplication的keyWindow的rootViewController开始寻找(如果有多个UIWindow则要考虑UIWindow的选择问题。

  在寻找的过程中,要分别考虑当前ViewController是UITabBarController和UINavigationController的情况,同时还要考虑到当前ViewController是否通过 presentViewController:animated:completion: 模态展示了其他ViewController。

2 实现方法

方法一:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- (UIViewController *)topViewController {
    UIViewController *resultVC;
    resultVC = [self _topViewController:[[UIApplication sharedApplication].keyWindow rootViewController]];
    while (resultVC.presentedViewController) {
        resultVC = [self _topViewController:resultVC.presentedViewController];
    }
    return resultVC;
}

- (UIViewController *)_topViewController:(UIViewController *)vc {
    if ([vc isKindOfClass:[UINavigationController class]]) {
        return [self _topViewController:[(UINavigationController *)vc topViewController]];
    } else if ([vc isKindOfClass:[UITabBarController class]]) {
        return [self _topViewController:[(UITabBarController *)vc selectedViewController]];
    } else {
        return vc;
    }
    return nil;
}

使用方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
UIViewController *topmostVC = [self topViewController];

方法二:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//获取当前屏幕显示的viewcontroller
- (UIViewController *)getCurrentVC
{
    UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    
    UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];
    
    return currentVC;
}

- (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC
{
    UIViewController *currentVC;
    
    if ([rootVC presentedViewController]) {
        // 视图是被presented出来的
        rootVC = [rootVC presentedViewController];
    }

    if ([rootVC isKindOfClass:[UITabBarController class]]) {
        // 根视图为UITabBarController
        currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];  
    } else if ([rootVC isKindOfClass:[UINavigationController class]]){
        // 根视图为UINavigationController
        currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];  
    } else {
        // 根视图为非导航类 
        currentVC = rootVC;
    }
    
    return currentVC;
}

解析代码主要使用了递归的思想(哈哈哈,毕业工作半年,发觉第一次写iOS用到递归,突然觉得高大上)。 [UIApplication sharedApplication].keyWindow.rootViewController获取到的是项目的根视图,结合可能用到UITabBarController或者UINavigationController作为导航结构,以及可能present出新的VC,其实如果用storyboard的方式写UI的话就很清晰,类似树的结构,再利用递归找到当前视图。

ps:

  如果是需要push新的视图,就非常简单了。用上面的方法获取到顶层的视图,判断currentVC.navigationController是否为nil。(为nil,则新建UINavigationController,然后再push;否则直接用currentVC.navigationController去push)。

三 扩展

如果用到的场景主要是vc里,可以弄成类别如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import "UIViewController+Helper.h"

@property (nonatomic, strong ,readonly) UIViewController * _Nullable currentVC;

//当前屏幕显示的viewcontroller
-(UIViewController *)currentVC{
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *controller = [self getCurrentVCFrom:rootViewController];
return controller;
}
//getCurrentVCFrom参考上文两种方法
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-02-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
iOS开发·UIWindow与视图层级调整技巧(makeKeyWindow,resignKeyWindow,makeKeyAndVisible,keyWindow,windowLevel,UIWind
例如,很多人习惯在keyWindow上添加一个自定义浮层视图,但是,当自己或者其它第三方框架曾经调高过其它自定义UIWindow属性windowLevel,或者有其它同级windowLevel的UIWindow后来改变过显示状态(如.hidden=NO,makeKeyAndVisible等),而且又没有 设将其设置为keyWindow,结果导致正在显示的UIWindow不是keyWindow,从而导致添加到keyWindow上自定义视图无法显示(被覆盖了)。
陈满iOS
2018/09/10
8.1K0
iOS开发·UIWindow与视图层级调整技巧(makeKeyWindow,resignKeyWindow,makeKeyAndVisible,keyWindow,windowLevel,UIWind
iOS接入开屏广告教程 : 以腾讯优量汇为案例
本文重点是拉取最新SDK库、iOS14的idfa适配以及iOS13的modal样式适配
公众号iOS逆向
2021/07/30
2.9K1
swift 获取控制器
得到view的控制器 /** view 获取它的控制器 */ public func viewController()->UIViewController? {
星宇大前端
2019/01/15
1.5K0
iOS初步集成极光推送后你还要做这些事
当我们把推送证书配置好再把极光SDK拖入项目配置,然后注册极光推送,完成代理,这样没有太多意外你就能收到消息了,但是我们都知道还需要做一些处理,都是哪些呢? ● 当收到消息时,app在前台如何处理 ● 在后台如何处理? ● 未启动如何处理? ● 当app在前台收到消息如何跳转到指定页面? ● 在后台收到系统通知,点击通知栏又如何跳转指定页面? ● 未启动时点击通知栏又如何跳转指定页面? ● 收到自定义通知如何显示? ● 怎么给指定用户发送消息? ● 当有多个类型通知的时候,怎么拿到服务
Raindew
2018/06/14
2.9K0
iOS 项目集成Flutter
最近移动端火爆无非是Flutter--舍我其谁,而官网的引导之中鲜有说怎么在已有项目中去集成Flutter,今天我们就再蹭个热门来进行一个iOS集成
大话swift
2019/07/03
1.4K0
iOS 项目集成Flutter
whose view is not in the window hierarchy!
需求:登录成功之后,需要判断是否绑定手机,没有绑定present一个手机页面,然后Tabbar切换到首页。这个需求还可以,但是业务里登录,注册,忘记密码等等都是modal出来的。所以登陆完之后不得不全部dissmiss掉,然后再通知到我的界面做相应操作。
星宇大前端
2019/01/15
1.6K0
UI篇-关于单个页面屏幕旋转要注意的问题
有时候,我们会需要在整个项目中,使某一个ViewController支持屏幕旋转,而其他的ViewController并不能自动旋转。这是一个很常见的需求,下面就屏幕旋转相关问题做个小结。
進无尽
2018/09/12
3.6K0
UI篇-关于单个页面屏幕旋转要注意的问题
iOS-UIWindow详解
1.UIWindow简介 UIWindow是一种特殊的UIView,通常在一个app中至少会有一个UIWindow。 iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的View,最后将控制器的View添加到UIWindow上,于是控制器的View就显示在屏幕上了。 一个iOS程序之所以能显示在屏幕上,完全是因为它有UIWindow,也就是说,没有UIWindow就看不到任何UI界面。 状态栏和键盘都是特殊的UIWindow。 那么UIWindow是如何将View显示到屏幕上的呢
xx_Cc
2018/05/10
2K0
IOS隐藏键盘
1、UIWebView加载网页后,点击网页内的链接在UIWebView内进行跳转时,键盘自动弹起;
meteoric
2018/11/19
1.3K0
iOS横竖屏切换
UIDeviceOrientation,表示设备朝向,可以通过[UIDevice currentDevice] orientation]获取,取值有:
落影
2022/09/28
2.7K0
iOS横竖屏切换
iOS获取当前显示UIViewController视图
- (UIViewController *)getCurrentVC { UIViewController *result = nil; UIWindow * window = [[UIApplication sharedApplication] keyWindow]; if (window.windowLevel != UIWindowLevelNormal) { NSArray *windows = [[UIApplication sharedApplicatio
Lee坚武
2020/12/01
9640
UINavigationController
UINavigationController 利用UINavigationController,可以轻松地管理多个控制器,轻松完成控制器之间的切换,典型例子就是系统自带的“设置”应用 UINavigationController的使用步骤 初始化UINavigationController 设置UIWindow的rootViewController为UINavigationController 根据具体情况,通过push方法添加对应个数的子控制器 UINavigationController以栈的形
用户1941540
2018/05/11
1.4K0
iOS 知识小集(Status Bar变换)
iOS 中经常会有需要在某个界面改变状态栏颜色或者某个界面隐藏状态栏的需求。而改变状态栏颜色和控制状态栏显示和隐藏的API,在iOS 的不同版本中也发生了很多变化。
Haley_Wong
2018/08/22
1.3K0
iOS 知识小集(Status Bar变换)
基础篇-UIApplication、UIWindow以及程序的启动流程看我就够了
这篇文章主要介绍下有关UIApplication、UIWindow以及程序的启动流程,通过这篇文章,相信你会更加理解iOS 的应用启动过程以及app应用级别的相关知识。
進无尽
2018/09/12
1.6K0
基础篇-UIApplication、UIWindow以及程序的启动流程看我就够了
【IOS开发基础系列】Storyboard专题
        如果你的 app 有大量的窗口,故事板能帮你减少许多用于从一个窗口转到另一个窗口的导航代码。与每个viewcontroller一个单独的 nib 文件不同,你的 app 只需用一个故事板文件(其中可以包含所有的viewcontroller 以及它们之间的关系)即可。
江中散人_Jun
2023/10/16
1.4K0
【IOS开发基础系列】Storyboard专题
iOS开发·runtime原理与实践: 消息转发篇(Message Forwarding) (消息机制,方法未实现+API不兼容奔溃,模拟多继承)
在我们开始使用消息机制之前,我们可以约定我们的术语。例如,很多人不清楚“方法”与“消息”是什么,但这对于理解消息传递系统如何在低级别工作至关重要。
陈满iOS
2018/09/10
2.1K0
iOS开发·runtime原理与实践: 消息转发篇(Message Forwarding) (消息机制,方法未实现+API不兼容奔溃,模拟多继承)
iOS 开发:『Runtime』详解(四)获取类详细属性、方法
文中示例代码在: bujige / YSC-Class-DetailList-Demo
程序员充电站
2019/08/02
2.9K0
大前端开发中的路由管理之四:iOS篇
1、iOS上的页面展示和逻辑 1.1 iOS的MVC设计模式         在介绍iOS的页面展示之前,我们需要先知道iOS应用的运行逻辑和设计模式。MVC即Model,View,Controller(模型,视图,控制器)。 View上展示的东西,由Model来定义 View上展示的逻辑,由Controller来控制 Controller同样负责初始化Model,和传递Model的信息给View         用户在View层中所进行的创建或修改数据的操作,通过Controller对象传达出去,最
QQ音乐技术团队
2021/11/15
1.9K0
iOS 测试 | iOS 自动化性能采集
​今天小编跟大家分享一篇来自学院内部学员的技术分享,本文主要介绍了作者在进行 iOS 自动化性能采集的一些经验,希望对大家在进行 iOS 自动化测试时有一些启发。
霍格沃兹测试开发
2020/07/15
2.3K0
iOS 测试 | iOS 自动化性能采集
iOS逆向(9)-Cycript,动态分析APP利器
https://juejin.im/post/5cc0986a6fb9a032453bb105”
iOSSir
2019/06/14
1.5K0
iOS逆向(9)-Cycript,动态分析APP利器
相关推荐
iOS开发·UIWindow与视图层级调整技巧(makeKeyWindow,resignKeyWindow,makeKeyAndVisible,keyWindow,windowLevel,UIWind
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文