Search code examples
swiftswiftuiuikit

Getting Dynamic UIColor from SwiftUI Color (light and dark mode)


It is possible through an easy initialiser to get the UIColor from a SwiftUI Color as follows:

let primary = UIColor(Color("primary"))

I added the Color with a light and dark mode in an Asset Catalogue. If primaryis used in UIKit Code it unfortunately only gives me the light mode Version and does not dynamically change the color for dark mode.

I do not know, how to get the dark and light mode color from a Color to write my own extension as a bridge.

Is there a solution or do you always start with UIColors and bridge it into SwiftUI Code? The project is still heavily based on UIKit, but new views are written in SwiftUI.


Solution

  • I don't think what you want is possible. To achieve that you needed an initializer of Color that takes a light and dark variant and a way to resolve to a cgColor given a certain interface style (both not possible afaik). But your common ground could be the color name of your color from the asset catalogue and you could derive your SwiftUI/UIKit colors from the identifier.

    struct ColorId: RawRepresentable, Equatable, Hashable {
        let rawValue: String
    
        init(_ rawValue: String) {
            self.init(rawValue: rawValue)
        }
    
        init(rawValue: String) {
            self.rawValue = rawValue
        }
    
        static let primaryText = ColorId("asset_name_of_primary_text_color")
    }
    
    extension ColorId {
        var color: Color { Color(rawValue) }
        var uiColor: UIColor? { UIColor(named: rawValue) }
    }
    
    struct SomeView: View {
        let textColor = ColorId.primaryText
        var body: some View { 
            Text("Text")
                .foregroundColor(textColor.color)  
        }
    }
    
    final class SomeUIView: UILabel {
        private let textColorId: ColorId
    
        init(textColorId: ColorId) {
            self.textColorId = textColorId
            super.init(frame: .zero)
            self.textColor = textColorId.uiColor
        }
        required init?(coder: NSCoder) { fatalError("need a color id") }
    }
    

    Then you pass around your color ids and get the UIColor or Color values when you need them. If you use something like RSwift you could also just pass around the ColorResource's.