Search code examples
iosobjective-cuiviewcontrolleruicolorios-darkmode

Objective-C - Change programmatically Gradient Background Color UIViewController When iOS 13 Dark Mode changed


I am implementing the features for the management of the Dark Mode of iOS 13 in my app .. I have a problem for the background of my ViewController.

My view controller has a background gradient color obtained with CAGradientLayer.

I managed to change the colors that make up the gradient based on the user's choice when it goes from Dark Mode ---> Light Mode and Light Mode ---> Dark Mode ..

My problem is that when the user sends in background my app to go to the control center and change the mode, the colors of the gradient I used for my background color do not change immediately ...

To get the gradient color changes the user must close the app and reopen it.

A really bad User Experince so I wanted to ask you how to solve this problem ...

This is what I use to change the colors of my gradient based on the user-selected iOS mode

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setupBackground];
}

- (void)setupBackground {

    UIColor *secondaryColor = self.view.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ? UIColor.customRedColor : UIColor.customGreenColor;

    CAGradientLayer *gradient = [CAGradientLayer layer];

    gradient.frame = UIApplication.sharedApplication.windows.firstObject.bounds;
    gradient.colors = @[(id)UIColor.customBlueColor.CGColor, (id)secondaryColor.CGColor];
    gradient.locations = @[@0.1, @0.9];

    [self.view.layer insertSublayer:gradient atIndex:0];
}

Solution

  • You should implement the traitCollectionDidChange and have it update your background:

    - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
        [super traitCollectionDidChange:previousTraitCollection];
    
        if (@available(iOS 13.0, *)) { // Needed if your app supports iOS 12
            if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
                [self setupBackground];
            }
        }
    }
    

    Of course this means that setupBackground will be called many times. So you should update it so it doesn't add a new layer each time.