Customize text color of UIDatePicker for iOS7 (just like Mailbox does) Customize text color of UIDatePicker for iOS7 (just like Mailbox does) ios ios

Customize text color of UIDatePicker for iOS7 (just like Mailbox does)


I need similar for my app and have ended up going the long way round. It's a real shame there isn't an easier way to simply switch to a white text version of UIDatePicker.

The code below uses a category on UILabel to force the label's text colour to be white when the setTextColor: message is sent to the label. In order to not do this for every label in the app I've filtered it to only apply if it's a subview of a UIDatePicker class. Finally, some of the labels have their colours set before they are added to their superviews. To catch these the code overrides the willMoveToSuperview: method.

It would likely be better to split the below into more than one category but I've added it all here for ease of posting.

#import "UILabel+WhiteUIDatePickerLabels.h"#import <objc/runtime.h>@implementation UILabel (WhiteUIDatePickerLabels)+ (void)load {    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        [self swizzleInstanceSelector:@selector(setTextColor:)                      withNewSelector:@selector(swizzledSetTextColor:)];        [self swizzleInstanceSelector:@selector(willMoveToSuperview::)                      withNewSelector:@selector(swizzledWillMoveToSuperview:)];    });}// Forces the text colour of the lable to be white only for UIDatePicker and its components-(void) swizzledSetTextColor:(UIColor *)textColor {    if([self view:self hasSuperviewOfClass:[UIDatePicker class]] ||       [self view:self hasSuperviewOfClass:NSClassFromString(@"UIDatePickerWeekMonthDayView")] ||       [self view:self hasSuperviewOfClass:NSClassFromString(@"UIDatePickerContentView")]){        [self swizzledSetTextColor:[UIColor whiteColor]];    } else {        //Carry on with the default        [self swizzledSetTextColor:textColor];    }}// Some of the UILabels haven't been added to a superview yet so listen for when they do.- (void) swizzledWillMoveToSuperview:(UIView *)newSuperview {    [self swizzledSetTextColor:self.textColor];    [self swizzledWillMoveToSuperview:newSuperview];}// -- helpers --- (BOOL) view:(UIView *) view hasSuperviewOfClass:(Class) class {    if(view.superview){        if ([view.superview isKindOfClass:class]){            return true;        }        return [self view:view.superview hasSuperviewOfClass:class];    }    return false;}+ (void) swizzleInstanceSelector:(SEL)originalSelector                 withNewSelector:(SEL)newSelector{    Method originalMethod = class_getInstanceMethod(self, originalSelector);    Method newMethod = class_getInstanceMethod(self, newSelector);    BOOL methodAdded = class_addMethod([self class],                                       originalSelector,                                       method_getImplementation(newMethod),                                       method_getTypeEncoding(newMethod));    if (methodAdded) {        class_replaceMethod([self class],                            newSelector,                            method_getImplementation(originalMethod),                            method_getTypeEncoding(originalMethod));    } else {        method_exchangeImplementations(originalMethod, newMethod);    }}@end


Here's a good working snippet. Tested on iOS 7.1, 8.0 and 8.1.

#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_8_1    #error "Check if this hack works on this OS"#endif    [self.datePicker setValue:[UIColor whiteColor] forKeyPath:@"textColor"];    SEL selector = NSSelectorFromString(@"setHighlightsToday:");    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDatePicker instanceMethodSignatureForSelector:selector]];    BOOL no = NO;    [invocation setSelector:selector];    [invocation setArgument:&no atIndex:2];    [invocation invokeWithTarget:self.datePicker];

I've added a simple condition to break the compilation process if you're building for iOS > 8.1, because I can't be sure that this hack will work, and you don't want to have any crashes in production because of this.

The setHighlightsToday: selector is used because UIDatePicker is using [UIColor blackColor] by default to display the current date.


I found the trick that set font color to any color and also dont mess up with Today label.

datePicker.setValue(UIColor.whiteColor(), forKeyPath: "textColor")datePicker.datePickerMode = .CountDownTimerdatePicker.datePickerMode = .DateAndTime //or whatever your original mode was

Here is the result:

And all the credits for this solution goes to this post in other thread:https://stackoverflow.com/a/33459744/1236334