Fixing iOS7 status bar

真的會被 iOS7 status bar 搞瘋~~

storyboard 的解法可以看這篇

這篇是針對不使用 storyboard 的解法。

option1: 直接對 AppDelegate 動手

Info.plist
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
AppDelegate.m
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
  [application setStatusBarStyle:UIStatusBarStyleLightContent];
  self.window.clipsToBounds =YES;
  self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20);
  //fixed scaling bugs - 可以試試 mark 掉下面這行的差別
  //self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
}

option2: viewDidLayoutSubviews

如有需要也可以針對特定的 view 調整 frame。

// fixing status bar in iOS7
- (void)viewDidAppear:(BOOL)animated
{
  [super viewDidAppear:animated];
  if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7"))
    self.view.frame = CGRectMake(0, -20, self.view.frame.size.width, self.view.frame.size.height);
}

// fixing status bar in iOS7
- (void)viewDidLayoutSubviews
{
  [super viewDidLayoutSubviews];
  if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7"))
    self.view.frame = CGRectMake(0, -20, self.view.frame.size.width, self.view.frame.size.height);
}

option3: Hiding status bar

或是乾脆隱藏...

BaseViewController.m
- (BOOL)prefersStatusBarHidden
{
  return YES;
}

Another issue

當使用presentViewController會將window.rootViewController.view往上推,新增一個方法來解決這個問題。
myUtil.m
+ (void)fixingStatusBarAfterPresenting:(UIViewController *)vc withAnimation:(BOOL)animation
{
  if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7")) {
    CGRect viewFrame = vc.view.frame;
    if(viewFrame.origin.y == 20) return;
    viewFrame.origin.y += 20.0;
    //已在 didFinishLaunchingWithOptions 處理過高度
    //viewFrame.size.height-= 20.0;
    if (animation == YES) {
      [UIView animateWithDuration:0.25 animations:^{
        vc.view.frame = viewFrame;
      }];
    }
    else vc.view.frame = viewFrame;    
    [vc.view layoutIfNeeded];
  }
}
解決 view 升起時,不要凸到 status bar 的位置。
myPresentViewController.m
- (void)viewDidLayoutSubviews
{
  [super viewDidLayoutSubviews];
  [TWECUtil fixingStatusBarAfterPresenting:self withAnimation:NO];
}
縮回去的時候,將 root view 調回來。
myPresentViewController.m
- (IBAction)onCancelBtnPressed:(id)sender
{
  [self dismissViewControllerAnimated:YES completion:^{
    TWECAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    [TWECUtil fixingStatusBarAfterPresenting:delegate.window.rootViewController withAnimation:YES];
  }];
}

參考資料1
參考資料2