在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的特性。实在开心,哈哈。

參考资料:

iOS7 隐藏状态栏 (电池栏)

Objective-C的hook方案(一): Method Swizzling

iOS 使用Method Swizzling隐藏Status Bar的更多相关文章

  1. 隐藏 Status Bar

    iOS6和iOS7在隐藏 Status Bar 三种方式比较: Storyboard 界面上选中UIViewController,最右边Simulated Metrics找到 Status Bar 设 ...

  2. iOS7下隐藏status bar的详细研究

    info.plist文件中,View controller-based status bar appearance项设为YES,则View controller对status bar的设置优先级高于a ...

  3. ios7上隐藏status bar

    在iOS7上 对于设置status bar 又有了点点的改变 1.对于 UIViewController 加入了动态改变 status bar style的方法 - (UIStatusBarStyle ...

  4. iOS7中彻底隐藏status bar

    用Xcode5开发新游戏,发现在iOS7中按照以前的方法隐藏status bar失效了. 想要彻底隐藏status bar,需要在info.plist中添加新行“View controller-bas ...

  5. ios开发中如何隐藏各种bar

    转载自http://www.cnblogs.com/lovecode/articles/2234557.html 状态条Status Bar [UIApplication sharedApplicat ...

  6. iOS 隐藏Status Bar

    要隐藏,有3个地方要做: 1.在info.Plist里,将该属性的hidden,设置为YES,这样,在启动时,就不会显示了: 2.在application-didFinish里面写,这样,可以隐藏io ...

  7. ios7适配--隐藏status bar

    //viewDidload if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { // iOS 7 ...

  8. iOS开发-UINavigationBar和Status Bar实用技巧

    iOS7之后关于UINavigationBar和Status  Bar都发生了一系列的改变,如果不需要兼容iOS7之后的设备,按照网上有些资料去解决问题会踩到一些坑.在iOS 7中,我们可以修改每个V ...

  9. 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 ...

随机推荐

  1. 0-20ma 0-5V,0-10V ,0-15V ,0-20V,0-30V模拟量(范围可以定制)多功能采集模块,支持1路继电器输出,2路Di输入,8路Ai输入,可电脑控制,支持485 modbus rtu协议。端口参数可以配置保存,支持定制修改。

    多功能模拟量采集模块MRD-5017具有8 通道模拟量采集(支持0-20mA,0-5V,0-10V混合测量),2路DI,1路继电器输出,1路485接口(支持MODBUS RTU),能实现8路AI(12 ...

  2. MacBook USB Type-C接口很美?其实是缩水的!

    苹果终于推出了12寸的全新MacBook,拥有2304×1440的高分辨率.蝶式结构全尺寸键盘.新的触摸板.14nm Core M处理器和无风扇设计,以及新的USB 3.1 Type-C接口.可以预料 ...

  3. 将Linux下编译的warning警告信息输出到文件中[整理笔记]

    Linux中,脚本语言环境中,即你用make xxx即其他一些普通linux命令,比如ls,find等,不同的数字,代表不同的含义: 数字 含义 标准叫法0 标准输入  stdin = standar ...

  4. 标头“Vary:Accept-Encoding”指定方法及其重要性分析

    原文地址:http://www.webkaka.com/blog/archives/how-to-set-Vary-Accept-Encoding-header.html 在webkaka的网站速度诊 ...

  5. Struts2 在Action中获取request、session、servletContext的三种方法

    首页message.jsp: <body> ${requestScope.req }<br/> ${applicationScope.app }<br/> ${se ...

  6. mount CIFS return ERR -12 and report Cannot allocate memory

    When I mount CIFS on board, it encountered error as below: # mount -t cifs //192.168.1.28/98share /t ...

  7. Java 基本日期类使用(一)

    一.java.util.Date Date表示特定的瞬间,精确到毫秒,其子类有Date.Time.Timestap.默认情况下输出的Date对象为:Mon Oct 13 17:48:47 CST 20 ...

  8. linux安装桌面软件

    CentOS 作为服务器的操作系统是很常见的,但是因为需要稳定而没有很时髦的更新,所以很少做为桌面环境.在服务器上通常不需要安装桌面环境,最小化地安装 CentOS(也就是 minimal CentO ...

  9. Notes里OK,CANCEL按钮的设定

    message并不能达到想要的目的: If Not udoc Is Nothing Then        'MessageBox "既にデータがあります.先月のデータを削除してください.& ...

  10. JS一些小算术、1加到50、乘法口诀表、买鸡等

    //从1加到50 for (var a=1,i=0;a<51; a++) {i=a+i} document.write(i);//1加到50 var num=0; for(var i=1;i&l ...