mardi 5 mai 2015

App Wide Themes in Swift on iOS

I have a solution, but to me it looks like a very hacky and not very elegant solution. But I searched, and searched, and could not find anything else. Maybe someone can suggest a better solution?

So, the problem, I want to have one file where I define all the colors and fonts and such of my app. I created a Style struct with a bunch of static vars like this:

struct Style{
    static var colorA = UIColor.redColor()
    static var colorB = UIColor.blackColor()
    static var titleText = colorA
    static var mainText = colorA
    static var backColor = colorB
    static var callBackColor = backColor
}

I have to use start var because I want to be able to reference previously declared variables in the definitions of new variables, and that's the only way I could make it work.

Overall above works well. In my code I can always reference a color or other purport as Style.titleText, for instance. So it looks like a good solution.

However, then I decided to add themes. To do so I added a static method called theme1 that overwrites some of the static vars from above and added a theme selector. Simple enough:

struct Style{
    static var colorA = UIColor.redColor()
    static var colorB = UIColor.blackColor()
    static var titleText = colorA
    static var mainText = colorA
    static var backColor = colorB
    static var callBackColor = backColor

    static func themeSelector(){
        // some logic loading defaults and running appropriate theme function bellow
    }

    static func theme1(){
        static var backColor = UIColor.greenColor()
        static var callBackColor = UIColor.greenColor()
    }
}

But then I ran into a problem, how to fire the themeSelector method? I tried overriding the initializer method and converting my struct to a class, but the initializer function would not fire in time, so some of variables that relied on the Style settings in their declaration statements would not load with updated theme settings, but rather with the defaults.

I also tried putting the call into the didFinishLaunchingWithOptions method of the AppDelegate, but same result as above.

I ended up doing something really idiotic looking, declaring a variable in my ViewController class like so:

var loadThem: Bool = {
    Style.themeSelector()
    return true
}()

This works, but..... really, is that the best way. Is there a better way to make themes? Is there a better way to call a function on load of a class or structure (overriding load method is not an option any more as of Swift 1.2). So, is there a better way?

Aucun commentaire:

Enregistrer un commentaire