iOS如何获取最顶层ViewController详解

1 获取当前屏幕显示的 Viewcontroller

//获取当前屏幕显示的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;
}

2 分析

2.1 UIApplication 的简析

UIApplication的核心作用是提供了iOS程序运行期间的控制和协作工作,每一个程序在运行期必须有且仅有一个UIApplication(或则其子类)的一个实例,在程序启动运行时,会在 main 函数中创建一个 UIApplication的单例实例,在代码中可以通过调用[UIApplication sharedApplication]来得到这个单例实例的指针。

2.2  KeyWindow  的简析

在简析 KeyWindow 前我们先来看一看 UIWindow 的概念

UIWindow 是 UIView 的子类,其在 UIView 添加了一些视图层级,管理视图,转发 UIEvent 对象的属性和 Method 等等

在上述实例中,我们通过  [UIApplication sharedApplication] 来获取的 UIApplication 的单例实例对象,然后通过实例对象的 keyWindow再获取到当前活跃的window(或者说是当前显示的主窗口).

KeyWindow 即指在IOS开发中活跃窗口,即能接到键盘和非触摸事件的一个窗口,一次只能有一个KeyWindow,在IOS 开发中,我们可以通过设置UIWindowLevel的数值来设置最前端的窗口为哪个,Level数值越高的窗口越靠前,如果两个窗口的Level等级相同,则我们可以通过makeKeyAndVisible来显示KeyWindow

(void)makeKeyWindow;//让当前UIWindow变成keyWindow(主窗口)
(void)makeKeyAndVisible;//让当前UIWindow变成keyWindow,并显示出来
[UIApplication sharedApplication].windows //获取当前应用的所有的UIWindow
[UIApplication sharedApplication].keyWindow //获取当前应用的主窗口
view.window ///获得某个UIView所在的UIWindow

makeKeyAndVisible 与 makeKeyWindow

  • makeKeyWindow: 只做了一件事就是使当前窗口成为主要窗口。 当前窗口不一定显示出来
  • makeKeyAndVisible : 做了两件事使当前窗口成为主要窗口并显示当前窗口。如果只想显示的话,我们还可以通过设置其属性hidden为 NO 即可。=

becomeKeyWindow 与 resignKeyWindow

  • becomeKeyWindow: 程序自动调用,用来通知其他窗口 当前容器已被设置为主窗口。 我们不要主动调用此方法, 此方法是系统自动调用的来发通知的,此方法的默认实现不执行任何操作,但子类可以覆盖它并使用它来执行与成为关键窗口相关的任务。
  • resignKeyWindow: 类似becomeKeyWindow, 其是调用以通知窗口它将要注销掉主键窗口的身份.同样的切勿直接调用此方法。

2.3 rootViewController属性

顾名思义:当前窗口的根视图

目前只有UIWindow有rootViewController这个属性,不要跟UINavigationController里面的根视图概念混淆。
UINavigationController其实并没有 rootViewController这个属性!也就没有自带的setter方法。要设置其根视图只能通过如下方法

- (instancetype)initWithRootViewController:(UIViewController *)rootViewController;

获取 uiwindow的根视图

方式一

AppDelegate *app =(AppDelegate *) [UIApplication sharedApplication].delegate;
UIViewController *rootViewController1 = appdelegate.window.rootViewController;

方式二

UIWindow *window = [UIApplication sharedApplication].keyWindow;
UIViewController *rootViewController2 = window.rootViewController;

需要注意的是:

在方式二中,UIAlertController、UIAlertView、UIActionSheet弹出后,上述这些View 出现生成了一个新的window,加在了界面上面,所以keyWindow就会变成UIAlertControllerShimPresenterWindow这个类

2.4 PresentedViewController 简析

在 ios 开发中,一般页面的组成有 NavigationController  或者 其他的 UiViewController、UITabViewController 等等,

  • 在有NavigationController导航栏的话,使用[self.navigationColler pushViewController:animated:] 进入到下一个视图 ,使用[self.navigationController popViewControllerAnimated:] 返回到上一视图。
  • 在没有NavigationController导航栏的时候,使用[self presentViewController:animated:completion:] 进入到下一个视图,使用 [self dismissViewControllerAnimated:completion:];返回到上一个视图中。

presentedViewController 与  presentingViewController

案例说明 A.presentedViewController A控制器跳转到B控制器;B.presentingViewController 就是返回到A控制器。

总结

到此这篇关于iOS如何获取最顶层ViewController的文章就介绍到这了,更多相关iOS获取最顶层ViewController内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • iOS开发中ViewController的页面跳转和弹出模态

    ViewController 页面跳转 从一个Controller跳转到另一个Controller时,一般有以下2种: 1.利用UINavigationController,调用pushViewController,进行跳转:这种采用压栈和出栈的方式,进行Controller的管理.调用popViewControllerAnimated方法可以返回. 复制代码 代码如下: PickImageViewController *ickImageViewController = [[PickImageV

  • iOS 获取当前的ViewController的方法

    本文介绍了iOS 获取当前的ViewController,分享给大家.具体如下 通过简单的判断[UIViewController class],就认定它是想要的控制器是不对的: if ([nextResponder isKindOfClass:[UIViewController class]]) { result = nextResponder; }else { result = window.rootViewController; } 因为:isKindOfClass:确定一个对象是否是一个类

  • iOS开发中的ViewController转场切换效果实现简介

    在iOS7之前,View Controller的切换主要有4种: Push/Pop,NavigationViewController Present and dismis Modal UITabBarController addChildViewController(一般用于自定义的继承于 UIViewController 的容器子类) iOS5,调用- (void)transitionFromViewController:(UIViewController *)fromViewControll

  • iOS如何获取最顶层ViewController详解

    1 获取当前屏幕显示的 Viewcontroller //获取当前屏幕显示的viewcontroller - (UIViewController *)getCurrentVC { ///下文中有分析 UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; UIViewController *currentVC = [self getCurrentV

  • IOS 获取网络图片大小实例详解

    IOS 获取网络图片大小实例详解 在iOS开发过程中经常需要通过网络请求加载图片,有时,需要在创建UIImageView或UIButton来显示图片之前需要提前知道图片的尺寸,根据图片尺寸创建对应大小的控件.但是对于网络图片来说,要想通过最优的方法获得尺寸就略微有点困难,大体思路就是下面这种: 如果有使用SDWebImage,则首先检查是否缓存过该图片,如果没有,先通过文件头获取图片大小(针对格式为png.gif.jpg文件获取其尺寸大小),如果获取失败,则下载完整的图片data,然后计算大小,

  • IOS之WebSocket框架Starscream案例详解

    传统的网络技术 (也就是 Berkeley sockets) 被认为是可靠和稳定的.但是 Berkeley socket 在某些 web 技术,比如代理和防火墙下不太好使.WebSocket 出现于 2011 年,是一种在客户端和服务端之间建立双向通讯的新技术.WebSocket 比起多个 HTTP 请求来说更有效率并允许长连接. 在 iOS 上使用 WebSocket 并不是那么容易.iOS 和 Mac 库 Starscream 的出现,极大地简化了 WebSocket 的创建和使用. 注:本

  • iOS封装倒计时按钮HLCountDownButton示例详解

    目录 引言 演示图 可选自定义属性 3种样式选择 回调说明 全局样式设置 引言 在开发中经常会用到倒计时的按钮,常用在发送短信验证码中.最差的写法是把代码写在ViewController中.这样的话如果项目中存在多个倒计时按钮,代码就十分臃肿了.所以封装一个倒计时按钮就迫在眉睫了.传送门HLCountDownButton,欢迎帮忙点点小星星 支持过xib.storyboard自定义样式 支持切换前后台计时准确 多种样式切换 支持CocoaPods导入pod "HLCountDownButton&

  • IOS文件的简单读写实例详解

    IOS文件的简单读写实例详解 数组(可变与不可变)和字典(可变与不可变)中元素对象的类型,必须是NSString,NSArray,NSDictionary,NSData,否则不能直接写入文件 #pragma mark---NSString的写入与读取--- //1:获取路径 NSString *docunments = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)firstObje

  • iOS NSURLProtocol的具体使用方法详解

    本文介绍了iOS NSURLProtocol的具体使用方法详解,分享给大家,具体如下: NSURLProtocol定义 这两天在优化项目,无意间看到了NSURLProtocol,学习一下顺便总结下来. NSURLProtocol也是苹果众多黑魔法中的一种,能够让你去重新定义苹果的URL加载系统 (URL Loading System)的行为,URL Loading System里有许多类用于处理URL请求,比如NSURL,NSURLRequest,NSURLConnection和NSURLSes

  • 基于iOS Realm数据库的使用实例详解

    首先下载Realm源代码,https://realm.io/cn/docs/objc/latest 将下载的文件解压,从 ios/static/ 目录中将 Realm.framework 拖曳到 Xcode 工程的文件导航器内,然后在 Xcode 文件导航器中选中工程.然后选择应用目标,前往 Build Phases 选项卡.在 Link Binary with Libraries 部分中单击 + 按钮,然后添加 libc++.tbd 和 libz.tbd.这样还没有完,我们还需要安装插件,打开

  • iOS开发之UIMenuController使用示例详解

    目录 简介 接口介绍 使用探索 如何创建并显示 UIMenuController 实现 Item 点击事件 菜单 Item 太多??? UIResponderStandardEditActions 协议 添加自定义菜单 箭头的方向 实际使用 总结 简介 UIMenuController 是一个菜单编辑界面,在很多地方都能用到,通常用于剪切.复制.粘贴.选择.全选和删除命令等,也可以自定义想要的操作,它长这样: 接口介绍 open class UIMenuController : NSObject

  • IOS Swift基础之switch用法详解

    IOS  Swift基础之switch用法详解 概述 Swift中的switch语句与Java等语言中的switch有很大的相似点,但是也有不同的地方,并且更加灵活. Swift中switch的case语句中不需要添加break Swift中需要考虑所有情况,default是必要的. case分支可以添加多个条件,用,分割 case不局限与常量,可以使使用范围 switch里可以使用元组 switch默认不需要添加break,执行一个case之后就跳出语句,如果想要继续下面的语句可以使用fall

  • IOS 指纹识别两种方式详解及实例

    IOS 指纹识别两种方式详解及实例 首先引入类名: #import <LocalAuthentication/LocalAuthentication.h> 然后在实现指纹识别的地方放入如下代码: 方式一: LAContext *lacontext = [[LAContext alloc]init]; // 判断设备是否支持指纹识别 BOOL isSupport = [lacontext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWit

随机推荐