Why is UIAppearance not being applied to UIAlertController in iOS 9?

My app supports back to iOS 5.1.1 so I use UIActionSheet and UIAlertView. These seem to translate to the new UIAlertController pretty well. However, the color of the buttons in these views are set using window.tintColor. This is a problem in my app since I use black toolbars with white text, but do NOT want white text on light grey. You'd think that iOS would be smart enough to not render text in unreadable colors.


Anyway, the only work around in iOS 8 is to set the appearnace of text views. Here's what I do in the app delegate...

[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor colorWithRed:0 green:(float)196/255 blue:(float)181/255 alpha:1]];

[[UILabel appearanceWhenContainedIn:[UIAlertController class], nil] setTextColor:[UIColor colorWithRed:0 green:(float)196/255 blue:(float)181/255 alpha:1]];


However, this does NOTHING in iOS 9 beta. I've issued a bug report since there appears to be no way to change the color of this text from window.tintColor.


Does anyone else have any ideas that I could try?

One workaround I came up with was to set the application delegate's window.tintColor to the desired color for the alert text right before presenting the UIAlertController. Then in the completion block for all of the UIAlertActions I set the window's tintColor back. It's a hack, I would rather not do it this way, but it works. I really hope this bug gets fixed by the time the Xcode 7 GM is available.

I found a solution to this. Not an elegant solution, but a solution.


I swizzled viewWillAppear: on UIAlertController, then looped through the views and modified the tint color. In my case I had a tintColor set on the entire window and despite setting the tintColor via appearance the UIAlertController maintained the color on the window. I check if the color is equal to that of the window and if so apply a new one. Blindly applying the tintColor to all views will result in the red tint on destructive actions to be reset.


+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method swizzleMethod = class_getInstanceMethod(self, @selector(viewWillAppear:));
        Method method = class_getInstanceMethod(self, @selector(alertSwizzle_viewWillAppear:));
        method_exchangeImplementations(method, swizzleMethod);
    });
}
- (void)alertSwizzle_viewWillAppear:(BOOL)animated
{
    [self alertSwizzle_viewWillAppear:animated];
    [self applyTintToView:self.view];
}
- (void)applyTintToView:(UIView *)view
{
    UIWindow *mainWindow = [UIApplication sharedApplication].keyWindow;

    for (UIView *v in view.subviews) {
        if ([v.tintColor isEqual:mainWindow.tintColor]) {
            v.tintColor = [UIColor greenColor];
        }
        [self applyTintToView:v];
    }
}


However this doesn't work on iOS 8, so you'll still need to set the apperance tint color.

[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor greenColor]];
Why is UIAppearance not being applied to UIAlertController in iOS 9?
 
 
Q