aaa
aaa

Reputation: 1649

Switch between two color schemes for an app?

For instance, I want light colors for all my views(background and labels) during the day and dark colors at night. The app will change its color automatically according to the time. Also the user will be able to switch to the other color scheme in settings. What is the most efficient way of doing this?

Multiple colors are involved in the switch (background and labels).

Upvotes: 3

Views: 845

Answers (2)

Steve Wilford
Steve Wilford

Reputation: 9002

I have done something very similar in the recent past; an app required various, user-selectable, colour schemes.

Theme

Create a Theme class with properties for each of your colour types. Try to stay away from describing the specific usage (submitButtonBackgroundColor), instead describe the purpose (this way you'll end up with much fewer colour definitions):

extern NSString * const ThemeChanged;

@interface Theme : NSObject

+ (Theme *)currentTheme;
+ (void)setCurrentTheme:(Theme *)theme;

@property (nonatomic, strong) UIColor *backgroundColor;
@property (nonatomic, strong) UIColor *foregroundColor;
@property (nonatomic, strong) UIColor *darkerForegroundColor;
@property (nonatomic, strong) UIColor *lighterForegroundColor;
@property (nonatomic, strong) UIColor *highlightColor;

@end

Implementation:

NSString * const ThemeChanged = @"ThemeChanged";

static Theme *_currentTheme = nil;

// Note this is not thread safe

@implementation Theme

+ (Theme *)currentTheme {
    return _currentTheme;
}

+ (void)setCurrentTheme:(Theme *)theme {
    _currentTheme = theme;

    [[NSNotificationCenter defaultCenter] postNotificationName:ThemeChanged object:nil];
}

@end

This class can then be instantiated with each of your desired schemes (one for day, one for night).

Each of your view controllers will need to access [Theme currentTheme] to retrieve the colours. They (your view controllers) can also register as an observer of the ThemeChanged notification in order to dynamically update their view's colours if/when you change the theme using setCurrentTheme:.

Day/Night detection

As for updating automatically based on the time of day you could use a repeating NSTimer with a reasonable interval, check the current time and call setCurrentTheme: with the dark theme object you created.

@interface DayNightHandler : NSObject
@property (nonatomic, strong) NSTimer *timer;

@end

@implementation DayNightHandler

- (instancetype)init
{
    self = [super init];
    if (self) {
        _timer = [NSTimer scheduledTimerWithTimeInterval:1
                                                  target:self
                                                selector:@selector(checkTime)
                                                userInfo:nil
                                                 repeats:YES];
    }
    return self;
}

- (void)checkTime {
    NSDate *currentDate = [NSDate date];
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitHour | NSCalendarUnitMinute
                                                                   fromDate:currentDate];

    NSLog(@"%@",components);

    // Very crude
    if (components.hour >= 18 || components.hour <= 6) {
        // set dark theme
    } else {
        // set light theme
    }
}

@end

You may want to swap out the crude day/night check for something a bit more solid, this is purely a high-level example intended to get you on the right track.

Upvotes: 6

Hitendra Solanki
Hitendra Solanki

Reputation: 4941

Create one property named appColor of type UIColor in AppDelegate.h File. Create its custom getter, and add your logic for timing as well as selection from settings.

Just set color by using,

self.view.backgroundColor = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).appColor

this will execute your custom getter method and return color as per your logic.

Upvotes: -3

Related Questions