Patching Mail controller on iOS
MFMailComposeViewController
has been around for a while and is the easiest way to send email from app.
It does its job okay, it has fine user interface and it takes care about email delivery, email accounts and many other things.
However everything goes wrong, once you customize UIAppearance
. It's kinda strange but this controller adopts only global style for UINavigationBar
and there is no way to directly change navigation bar appearance, even though essentially it is navigation controller.
The customization options for this controller are quite limited since it has Remote View Controller under the hood running in separate process. But we still can customize navigation bar.
I use a screenshot from message controller which is very similar to mail controller, but breaks a bit more than mail controller.
Since it takes appearance from global UINavigationBar
style, we can swap styles between showing and hiding mail controller. Timing is very important here, to avoid the rest of the app from falling apart.
The same approach can be used for MFMessageComposeViewController
.
#import <MessageUI/MessageUI.h>
@interface MFMailComposeViewControllerSubclass : MFMailComposeViewController
@end
static id originalTintColor;
static id originalBarTintColor;
static id originalTitleTextAttributes;
@implementation MFMessageComposeViewControllerSubclass
- (id)init {
[self patch];
if(!(self = [super init])) {
[self unpatch];
}
return self;
}
- (void)patch {
id navigationBarAppearance = [UINavigationBar appearance];
// Save original appearance
originalTintColor = [navigationBarAppearance tintColor];
originalBarTintColor = [navigationBarAppearance barTintColor];
originalTitleTextAttributes = [navigationBarAppearance titleTextAttributes];
// Reset to default appearance
[navigationBarAppearance setTintColor:nil];
[navigationBarAppearance setBarTintColor:nil];
[navigationBarAppearance setTitleTextAttributes:nil];
}
- (void)unpatch {
id navigationBarAppearance = [UINavigationBar appearance];
[navigationBarAppearance setTintColor:originalTintColor];
[navigationBarAppearance setBarTintColor:originalBarTintColor];
[navigationBarAppearance setTitleTextAttributes:originalTitleTextAttributes];
originalBarTintColor = nil;
originalBarTintColor = nil;
originalTitleTextAttributes = nil;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self unpatch];
}
@end