Anyone can help me, Ive just starting to study swift, and now doing the iOS App Dev Tutorial (Scrumdinger), so, in some part of the tutorial I
ve created this enum, and it didn't get the colors when used the var mainColor, or didn't get the capitalized string o the value, when used the var name, just return yellow (not capitalized) for example.
How are you testing that?
print(Theme.yellow.name)
should give you "Yellow"
Colours are more tricky: while there are Color.red
, Color.green
, etc, AFAIK there is no way to get the standard colour by name "red", "green", etc unless you put the correspondingly named colours in the asset catalogue.
I have just checked and this is the result:
let mainColor = Theme.teal.mainColor
print(mainColor) // NamedColor(name: "teal", bundle: nil)
let name = Theme.indigo.name
print(name) // Indigo
It seems that the name is returned capitalised as expected, but the Color
call is looking for a color in your app bundle (assets). If you have not declared the colors there, you will not get it. This means that this should not be a problem of the enum, but of the way Color
is initialised.
P.S.: If you paste the code and use the code formatting option, it is easier to reproduce the problem. :)
P.P.S.: Color
is part of Apple's SwiftUI framework and not of Swift
Theme file that has the enum
import SwiftUI
enum Theme: String {
case bubblegum
case buttercup
case indigo
case lavender
case magenta
case navy
case orange
case oxblood
case periwinkle
case poppy
case purple
case seafoam
case sky
case tan
case teal
case yellow
var accentColor: Color {
switch self {
case .bubblegum, .buttercup, .lavender, .orange, .periwinkle, .poppy, .seafoam, .sky, .tan, .teal, .yellow: return .black
case .indigo, .magenta, .navy, .oxblood, .purple: return .white
}
}
var mainColor: Color {
Color(rawValue)
}
var name: String {
rawValue.capitalized
}
}
Class that actually initialize the Theme:
import Foundation
struct DailyScrum: Identifiable {
let id: UUID
var title: String
var attendees: Array<Attendee>
var lengthInMinutes: Int
var lengthInMinutesAsDouble: Double {
get {
Double(lengthInMinutes)
}
set {
lengthInMinutes = Int(newValue)
}
}
var theme: Theme
init(id: UUID = UUID(), title: String, attendees: Array<Attendee>, lengthInMinutes: Int, theme: Theme) {
self.id = id
self.title = title
self.attendees = attendees
self.lengthInMinutes = lengthInMinutes
self.theme = theme
}
}
extension DailyScrum {
struct Attendee: Identifiable {
let id: UUID
var name: String
init(id: UUID = UUID(), name: String) {
self.id = id
self.name = name
}
}
}
extension DailyScrum {
static let sampleData: Array<DailyScrum> = [
DailyScrum(title: "Design",
attendees: [Attendee(name: "Diego"), Attendee(name: "Roberto"), Attendee(name: "Rodrigo")],
lengthInMinutes: 10,
theme: .yellow),
DailyScrum(title: "App dev",
attendees: [Attendee(name: "Diego"), Attendee(name: "Roberto"), Attendee(name: "Rodrigo")],
lengthInMinutes: 15,
theme: .indigo),
DailyScrum(title: "Start backend",
attendees: [Attendee(name: "Diego"), Attendee(name: "Roberto"), Attendee(name: "Rodrigo")],
lengthInMinutes: 30,
theme: .purple)
]
static var emptyScrum: DailyScrum {
DailyScrum(title: "", attendees: [], lengthInMinutes: 5, theme: .sky)
}
}
So when im using im actually using this way:
NavigationLink(destination: DetailView(scrum: scrum)) {
CardView(scrum: scrum)
}
.listRowBackground(scrum.theme.mainColor)
Ok, but have you declared your colors in the assets catalogue like this?:
Because:
Color("orange") // looks for a color called "orange" in the assets catalogue
Color(.orange) // gives your the color "orange" - this is a static let declared in the SwiftUI Color class....
and Color(rawValue)
behaves just like Color("orange")
Oh, I haven't created this asset catalogue, will try to find out how to create
This instruction covers the topic very well:
Still a problem with capitalisation?
This is a bit odd limitation that standard colours like red, green, etc are not available via Color(systemName:)
. Here's a possible workaround:
import SwiftUI
#if canImport(UIKit)
import UIKit
extension Color {
init?(systemName: String) {
let sel = Selector(systemName)
guard UIColor.self.responds(to: sel),
let result = UIColor.self.perform(sel) else {
print("no such system, color: \(systemName)")
return nil
}
let object = result as Unmanaged<AnyObject>
let color = object.takeUnretainedValue() as! UIColor
self.init(color)
}
}
#endif
#if canImport(Cocoa)
import Cocoa
extension Color {
init?(systemName: String) {
let sel = Selector(systemName)
guard NSColor.self.responds(to: sel),
let result = NSColor.self.perform(sel) else {
print("no such system, color: \(systemName)")
return nil
}
let object = result as Unmanaged<AnyObject>
let color = object.takeUnretainedValue() as! NSColor
self.init(color)
}
}
#endif
Should work for both UIKit and Cocoa clients utilising Obj-c's performSelector feature. Minimally tested.
PS. forgot to mention: systemName should be in the form: "systemRedColor"
, "systemBlueColor"
and so on.