17

I am using the UIAppearance protocol to set the background image of UINavigationBar objects throughout my app.

[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"image-name"] forBarMetrics:UIBarMetricsDefault];

I would like to override this for instances of MFMailComposeViewController so that the default style navigation bar is displayed. I attempted to use appearanceWhenContainedIn to set this and this works on iOS 5 but not on iOS 6.

[[UINavigationBar appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];

Am I making an error or is there a better way to accomplish this?

markdorison
  • 139,374
  • 27
  • 55
  • 71

3 Answers3

24

Changing the appearance of a MFMailComposer through normal measures is not possible, but there is a little workaround you can do, which I've used many times before.

Add two methods to the class in which you wish to implement the new look to:

- (void)applyComposerInterfaceAppearance
{
    [[UINavigationBar appearance] setTintColor:[UIColor blueColor]];
}

- (void)applyGlobalInterfaceAppearance
{
    // My default color of choice
    [[UINavigationBar appearance] setTintColor:[UIColor redColor]];
}

Now in your show method, apply the special composer interface changes you'd like to make.

- (void)showMailComposer
{
    if ([MFMailComposeViewController canSendMail]) 
    {
        [self applyComposerInterfaceApperance];

        MFMailComposeViewController *viewController = [[MFMailComposeViewController alloc] init];
        viewController.mailComposeDelegate = delegate;
        [viewController setToRecipients:mailRecepients];
        [viewController setSubject:mailSubject];
        [viewController setMessageBody:messageBody isHTML:NO];
        [self presentModalViewController:viewController animated:YES];
    }
}

And in your delegate, change the interface back to the way it was.

- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
    // Do normal mail composer did finish stuff in here
    [self applyGlobalInterfaceAppearance];
}
Maxim Pavlov
  • 2,962
  • 1
  • 23
  • 33
mergesort
  • 672
  • 4
  • 10
  • This is what I do in my own apps too. I have a pair of setAppearance and unsetAppearance methods in my app delegate that I can call anywhere to turn on and off all my UI customizations whenever I need to present a standard prebaked view controller (the mail controller, iPod library picker, etc). – Ziconic Mar 22 '13 at 23:15
  • 2
    @Ziconic, could you please tell me how you "unset" your uiappearance properties on the fly? thank you – Pavan Oct 28 '14 at 05:49
  • in my condition this logic worked with setBarTintColor. not with seTintColor. – Dipen Desai Nov 14 '18 at 13:07
2

The Mail Composer view is run in a different process under iOS 6 and cannot be tampered with directly (since the view is essentially inside another app). You cannot customize what it shows, it's the same for the Twitter & Facebook views.

Here is a more detailed description of remote view controllers: http://oleb.net/blog/2012/10/remote-view-controllers-in-ios-6/

Hampus Nilsson
  • 6,692
  • 1
  • 25
  • 29
  • 3
    Even though it is run in a remote process, that is an implementation detail not exposed to the developer; as far as the developer is concerned, it looks the same as before. I would suggest filing a bug if it's not working; I know that the remote view controller mechanism does at least *something* with the UIAppearance mechanism, because I have crash logs down in there. :) – BJ Homer Mar 22 '13 at 21:58
  • The main view is indeed in a different process but the navigation bar and the navigation controller it's in are in the same process as your app and are styled according to your UIAppearance customizations. – Ziconic Mar 22 '13 at 23:12
  • @BJHomer I filed a radar. Feel free to dupe. rdar://13490724 – markdorison Mar 23 '13 at 21:10
1

Simply set the tintColor on the MFMailComposeViewController instance:

[mailInstance.navigationBar setTintColor:[UIColor someColor]];
SmileBot
  • 19,393
  • 7
  • 65
  • 62