4

Problem: My status bar appears on top of navigationBar after I present and dismiss MFMailComposerViewController as modal view.

-(IBAction)openMail:(id)sender
{
    MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
    mc.mailComposeDelegate = self;

    [mc setSubject:emailTitle];
    [mc setMessageBody:messageBody isHTML:YES];
    [mc setToRecipients:toRecipents];
    [mc.navigationItem.leftBarButtonItem setTintColor:[UIColor colorWithRed:144/255.0f green:5/255.0f blue:5/255.0f alpha:1.0f]];
    [self presentViewController:mc animated:YES completion:NULL];
}


- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
switch (result)
{
    case MFMailComposeResultCancelled:
        NSLog(@"Mail cancelled");
        break;
    case MFMailComposeResultSaved:
        NSLog(@"Mail saved");
        break;
    case MFMailComposeResultSent:
        NSLog(@"Mail sent");
        break;
    case MFMailComposeResultFailed:
        NSLog(@"Mail sent failure: %@", [error localizedDescription]);
        break;
    default:
        break;
}
// Reset background image for navigation bars
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"navigationBar.png"] forBarMetrics:UIBarMetricsDefault];
NSLog(@"%@",[GGStackPanel printFrameParams:self.view]);
// Close the Mail Interface
GGAppDelegate * appDel = [[UIApplication sharedApplication] delegate];

HHTabListController * contr = (HHTabListController*)appDel.viewController;
[contr setWantsFullScreenLayout:NO];
NSLog(@"%i",[contr wantsFullScreenLayout]);
[self dismissViewControllerAnimated:YES completion:NULL];

}

There are couple of similar questions on Stackoverflow, but none of the solutions suggested there work for me. I have already tried:

status bar and Navigation bar problem after dismissed modal view

http://developer.appcelerator.com/question/120577/nav-bar-appears-underneath-status-bar

I tried presenting and dismissing from AppDelegate, no help.

Changing the view frame or navigationBar frame works, but I would have to do the same thing for all other views in my app (there are many of them). That will make my whole app depend on this tiny bug.

Screenshots

View before presenting

After dismissing MailComposer:

View after dismissing

Community
  • 1
  • 1
AzaFromKaza
  • 768
  • 1
  • 10
  • 24
  • Can you post a screenshot? – Undo Apr 13 '13 at 02:21
  • Is the MailComposer presented full screen? – oiledCode Apr 13 '13 at 08:52
  • I don't think so. I checked the value of self.wantsFullScreenLayout, it's NO. I tried to play around with self.wantsFullScreenLayout, even tried to change appDelegate.viewController's and MailComposer's wantsFullScreenLayout property --> no change. – AzaFromKaza Apr 13 '13 at 13:35
  • It looks like your main ViewController has incorrect logic for layout. What is "HHTabListController"? – Adam Apr 13 '13 at 17:49
  • I used HHTabListController as a super viewController. I wanted to have a vertical tabBar, like Facebook app does. So I found [its close implementation here](https://github.com/gloubibou/HHTabListController) I thought maybe if I set hhTabListController's wantsFullScreenLayout to NO that will fix the problem, but apparently it does not. – AzaFromKaza Apr 13 '13 at 19:17
  • @Adam could you explain what do you mean by incorrect logic for layout? – AzaFromKaza Apr 13 '13 at 19:22
  • did u try to put this code `[[UIApplication sharedApplication]setStatusBarHidden:YES];` after presenting your view controller ? – limon Apr 13 '13 at 21:21

2 Answers2

3

wantsFullScreenLayout is something complex and unrelated. ALL viewcontrollers are required to EITHER be embedded inside a "layout" viewcontroller (Apples UINavigationController, Apple's UITabBarController), OR to fully implement the complex logic of "how big should I be, and where am I positioned?" themselves.

Apple decided with iOS 1.0 that the main iPhone view you see DOES NOT START at 0,0. The Window that contains it starts at (0,0), but it is OVERLAPPED by the status bar.

I think this is a decision they came to regret, it made sense at the time, but in the long term it caused a lot of bugs.

The net effect is:

  1. UINavigationController and UITabBarController have special (undocumented) internal code that makes it SEEM AS IF (0,0) is the top left corner - they force-resize/reposition any UIViewController's you add to them
  2. ...if you are NOT using one of them as your main controller, you have to re-implement that logic yourself. If you're using 3rd-party UIViewController instance, the logic is often implemented incorrectly or missing.
  3. ... you can FIX THIS yourself at runtime by re-positioning the UIViewController.view (its root view), e.g. by this:

(code)

UIViewController* rootController = // in this case HHTabController?
UIView* rootView = rootController.view;
CGRect frame = rootView.frame;
CGPoint oldOrigin = frame.origin;
CGPoint newOrigin = // calculate this, according to Apple docs.
// in your current case, it should be: CGPointMake( 0, 20 );
frame.origin = newOrigin;
frame.size = CGSizeMake( frame.size.width - (newOrigin.x - oldOrigin.x), frame.size.height - (newOrigin.y - oldOrigin.y) );
rootView.frame = frame;

...obviously, it's annoying having to do this everytime. This is why Apple strongly encourages everyone to use UINavigationController and/or UITabBarController :)

Adam
  • 32,900
  • 16
  • 126
  • 153
  • I guess I need to read Apple Docs more carefully :) But anyways, this actually helped. – AzaFromKaza Apr 13 '13 at 21:50
  • I was also wondering if I should move the rootController's view frame back by shifting it up by 20px, so that other subviews of HHTabController do not get shifted down, but it seems like other views are not affected at all, even if I call MailComposer several times (which triggers the repositioning code above). Do you know why is that? – AzaFromKaza Apr 13 '13 at 21:52
  • To work out what's happening wit the other views, you'll need to carefully examine the runtime .frame AND .bounds of every view on screen - any parent view might be auto-correcting the values for its children. – Adam Apr 13 '13 at 23:09
0

This alternative solution is also really handy to handle the weird behaviour of top layout guide repositioning itself after view controller is presented modally.

Add constraint for top spacing not to "Top Layout Guide", but to the actual "view". Select view (current distance ...) as shown in screenshot below: enter image description here

Courtesy: https://stackoverflow.com/a/24818204/2959346

HeadOnn
  • 1,480
  • 14
  • 21