iOS 使用Method Swizzling隐藏Status Bar
在iOS 6中,隐藏Status Bar很的简单。
// iOS 6及曾经,隐藏状态栏
[[UIApplication sharedApplication] setStatusBarHidden:YES];
来到了iOS 7的年代以后,须要在UIViewController中指定:
#ifdef __IPHONE_7_0
- (BOOL)prefersStatusBarHidden {
return YES;
}
#endif
并通过下列代码刷新状态栏:
if ([viewController respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
        [viewController prefersStatusBarHidden];
        [viewController performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
}
可是上述代码并非万能的,iOS 7的某些场合还是会造成无法隐藏Status Bar的问题。
在ParentViewController中Add一个ChildViewController,假设ParentViewController的
prefersStatusBarHidden方法返回的是NO,那么即使ChildViewController中的prefersStatusBarHidden方法返回的是YES并调用以上代码。也无法隐藏Status Bar。
解决方式:Method Swizzling
在ChildViewController中Hook ParentViewController的prefersStatusBarHidden方法,使其返回YES,然后调用更新状态栏的代码,实现隐藏状态栏。须要注意的是。在适当场合,比如ChildViewController的viewWillDisappear方法中。须要将Hook的方法还原。否则可能造成奇怪的情况出现。
代码例如以下:
1.在ChildViewController的viewDidLoad方法中替换ParentViewController的prefersStatusBarHidden方法的实现
- (void)viewDidLoad {
    [super viewDidLoad];
    _statusBarHidden = [UIApplication sharedApplication].statusBarHidden;
    // 进入界面时隐藏状态栏
    UIViewController *parentViewController = self.parentViewController;
    if ([parentViewController respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
        [self hookPrefersStatusBarHidden:parentViewController];
    }
    else {
        // iOS 6及曾经,隐藏状态栏
        [[UIApplication sharedApplication] setStatusBarHidden:YES];
    }
}
2.使用Runtime的Method Swizzling大法替换ChildViewController和ParentViewController两者的prefersStatusBarHidden方法的实现
- (void)hookPrefersStatusBarHidden:(UIViewController *)parentViewController {
    /**
     Method Swizzling
     1.假设ParentViewController的prefersStatusBarHidden返回NO。那么Add在其上的ChildViewController的prefersStatusBarHidden即使返回YES,也无法隐藏状态栏。因此在viewDidLoad时。须要将ParentViewController中prefersStatusBarHidden方法的实现替换掉
     2.在viewWillDisappear时。须要将交换的方法实现还原回来
     */
    Method src_method = class_getInstanceMethod([UIViewController class], @selector(prefersStatusBarHidden));
    Method des_method = class_getInstanceMethod([self class], @selector(hook_prefersStatusBarHidden));
    method_exchangeImplementations(src_method, des_method);
    // 刷新状态栏
    dispatch_async(dispatch_get_main_queue(), ^{
        [parentViewController prefersStatusBarHidden];
        [parentViewController performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
    });
}
- (BOOL)hook_prefersStatusBarHidden {
    // 隐藏状态栏
    return YES;
}
3.在ChildViewController从ParentViewController中移除时。viewWillDisappear方法必然会被调用(注意不要在viewDidDisappear方法中调用,此时ChildViewController可能已经被释放掉),因此能够在该方法中还原两者的prefersStatusBarHidden的实现
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    // 退出界面时。还原状态栏的初始状态
    UIViewController *parentViewController = self.parentViewController;
    if ([parentViewController respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
        [self hookPrefersStatusBarHidden:parentViewController];
    }
    else {
        // iOS 6及曾经,恢复状态栏的初始状态
        [[UIApplication sharedApplication] setStatusBarHidden:_statusBarHidden];
    }
}
有时候为了确保状态栏隐藏。能够强制运行以上代码。
在实际project中第二次用上Runtime的特性。实在开心,哈哈。
參考资料:
iOS 使用Method Swizzling隐藏Status Bar的更多相关文章
- 隐藏 Status Bar
		iOS6和iOS7在隐藏 Status Bar 三种方式比较: Storyboard 界面上选中UIViewController,最右边Simulated Metrics找到 Status Bar 设 ... 
- iOS7下隐藏status bar的详细研究
		info.plist文件中,View controller-based status bar appearance项设为YES,则View controller对status bar的设置优先级高于a ... 
- ios7上隐藏status bar
		在iOS7上 对于设置status bar 又有了点点的改变 1.对于 UIViewController 加入了动态改变 status bar style的方法 - (UIStatusBarStyle ... 
- iOS7中彻底隐藏status bar
		用Xcode5开发新游戏,发现在iOS7中按照以前的方法隐藏status bar失效了. 想要彻底隐藏status bar,需要在info.plist中添加新行“View controller-bas ... 
- ios开发中如何隐藏各种bar
		转载自http://www.cnblogs.com/lovecode/articles/2234557.html 状态条Status Bar [UIApplication sharedApplicat ... 
- iOS 隐藏Status Bar
		要隐藏,有3个地方要做: 1.在info.Plist里,将该属性的hidden,设置为YES,这样,在启动时,就不会显示了: 2.在application-didFinish里面写,这样,可以隐藏io ... 
- ios7适配--隐藏status bar
		//viewDidload if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { // iOS 7 ... 
- iOS开发-UINavigationBar和Status  Bar实用技巧
		iOS7之后关于UINavigationBar和Status Bar都发生了一系列的改变,如果不需要兼容iOS7之后的设备,按照网上有些资料去解决问题会踩到一些坑.在iOS 7中,我们可以修改每个V ... 
- Status bar and navigation bar appear over my view's bounds in iOS 7
		转自:http://stackoverflow.com/questions/17074365/status-bar-and-navigation-bar-appear-over-my-views-bo ... 
随机推荐
- Windows 10开发基础——文件、文件夹和库(一)
			原文:Windows 10开发基础--文件.文件夹和库(一) 主要内容: 1.枚举查询文件和文件夹 2.文本文件读写的三种方法——创建写入和读取文件 3.获得文件的属性 枚举查询文件和文件夹 先了解一 ... 
- Javascript禁止父元素滚动条滚动, pc、移动端均有效
			在网页中经常会遇到这样的场景, 网页比较长有滚动条, 然后网页内的某个内容块里面的内容也比较长, 也具有滚动条.当鼠标移到内容块中使用滚动条来滚动查看内容到达底部或头部的时候,父元素的滚动条也就开始滚 ... 
- poj2909 || poj2262
			#include <stdio.h> #include <stdlib.h> #include<math.h> int isPri(int a, int b) { ... 
- HTML5全屏API
			现在大多数浏览器都有全屏功能,允许用户来设置或操作.但HTML5的全屏API与之不同,HTML5的全屏API允许web开发工程师在程序中调用. 这样,web开发工程师就可以再网站中设计一个按钮,当该按 ... 
- Python学习笔记7-把函数当参数传递、指定可变参数
			把函数当参数传递 # 函数参数传递 # 面向对象编程就是把对象传来传去 # 面向函数编程就是把函数传来传去 def mytest(num): return num * 2 # # 不光可以传递变量,还 ... 
- Mac  任何选项没有了怎么办?
			1.如果需要恢复允许"任何来源"的选项,即关闭 Gatekeeper,请打开终端 2.然后使用 spctl 命令: sudo spctl --master-disable 
- wcf系列学习5天速成——第五天 服务托管
			今天是系列的终结篇,当然要分享一下wcf的托管方面的知识. wcf中托管服务一般有一下四种: Console寄宿: 利于开发调试,但不是生产环境中的最佳实践. winform寄 ... 
- SQL Server执行计划那些事儿(1)——哈希、合并、嵌套联接的选择
			接下来的文章是记录自己曾经的盲点,同时也透漏了自己的发展历程(可能发展也算不上,只能说是瞎混).当然,一些盲点也在工作和探究过程中慢慢有些眉目,现在也愿意发扬博客园的奉献精神,拿出来和大家分享一下. ... 
- windows下如何安装配置mysql-5.7-m14-winx64(zip格式的安装)
			win7 64位下如何安装配置mysql-5.7.4-m14-winx64 1. mysql-5.7.4-m14-winx64.zip下载 官方网站下载地址:http://dev.mysql.co ... 
- lightoj 1064 Throwing Dice
			题意:给你n个骰子,求n个骰子的和不小于x的概率. 刚开始想每给一组数就计算一次~~太笨了- -,看了别人的代码,用dp,而且是一次就初始化完成,每次取对应的数据就行了.WA了好多次啊,首先不明白的就 ... 
