I'm rewriting my app in Swift (yes, hooray) and I'm running into the following:
I inherited a class, of which the definition is (.h)
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface MWColor : NSObject
+ (UIColor *)gray;
+ (UIColor *)green;
+ (UIColor *)themeColor;
#end
In here, I define colors, that I can use throughout my project as such:
myView.backgroundColor = MWColor.gray()
Now, I want to do this in a proper Swift way.
What would be the best approach? Extensions?
Help me to be a good Swift citizen
You can add computed colours to UIColor in an extension like this...
extension UIColor {
static var myRed: UIColor {
// define your color here
return UIColor(...)
}
}
or even...
extension UIColor {
static let myRed = UIColor(... define the color values here ...)
}
Then access it like...
let someColor: UIColor = .myRed
or
let otherColor = UIColor.myRed
This matches the way that standard colours are defined too..
UIColor.red
UIColor.yellow
UIColor.myRed
etc...
There are probably a thousand different ways to do this, but I use the following extension:
extension UIColor {
convenience init(rgb: UInt) {
self.init(
red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgb & 0x0000FF) / 255.0,
alpha: CGFloat(1.0)
)
}
}
Then you can set the color of any object using the common HEX color code of RGB colors. Quickly find HEX colors here: http://www.color-hex.com/
view.backgroundColor = UIColor(rgb: 0xFF0000) will set the backgroundColor of view to red.
Hope this helps
Related
I tried the steps below to expeand UIColor, but it didn't work.
At first, I added new color set in xcassets,
and then add UIColor + Extension.swift in my project folder.
// UIColor + Extension.swift
import Foundation
import UIKit
extension UIColor {
class var testColor1:UIColor {
return UIColor(red: 210.0/255.0, green: 105.0/255.0, blue: 130.0/255.0, alpha: 1.0)
}
class var testColor2: UIColor? { return UIColor(named: "testColor") }
}
I want to load custom color in AppDelegate.mm, but got the following error.
animationUIView.backgroundColor = [UIColor testColor1];
The code above doesn't work either.
What am I doing wrong?
I'm sorry, but I'm making a project with react native, so I don't know Swift and objective c well.
if you want to change a background with a custom color you should use :
someView.backgroundColor = UIColor(named: "testColor1")
Apple recommends using system colors to adapt apps to light and dark mode automatically, for example:
myLabel.textColor = UIColor.secondaryLabel
Here Apple lists various properties to be used, such as the one in the example above, and system colors for background, placeholder text, and more.
But it doesn't list a property for UIButton elements.
Which property or other method should we use to adapt UIButtons to theme changes?
As of now, I'm doing this:
myButton.tintColor = UIColor.link
which is supposedly for links but is the only "clickable" property I found.
I'm not looking to use something like UIColor.systemRed, rather something like UIColor.systemBackground, which adapts automatically to the current theme.
I hope you create colored Assets not one by one. You can use this function to tint images as a extension of UIImageView. I also use the same technique for buttons.
func setImageAndColor(image: UIImage, color: UIColor) {
let templateImage = image.withRenderingMode(.alwaysTemplate)
self.image = templateImage
self.tintColor = color
}
In case you want to define all you own colors, I suggest to create a singleton class named Colors:
import UIKit
class Colors {
static let shared = Colors()
var statusBarStyle: UIStatusBarStyle = .lightContent
private init(){}
func setLightColors() {
statusBarStyle = .darkContent
yourColor = UIColor( // choose your favorite color
styleColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1)//white
labelColor = UIColor(red: 15/255, green: 15/255, blue: 15/255, alpha: 1)
subLabelColor = UIColor(red: 25/255, green: 25/255, blue: 25/255, alpha: 1)
............ set values for all colors from here.
}
func setDarkColors() {
statusBarStyle = .lightContent
yourColor = // choose your favorite color
............
}
// set initial colors
var yourColor: UIColor =
}
If somebody is interested in the whole Colors class, text me or comment below.
I access the colors singleton by:
Colors.shared.yourColor
Also for first configuration I set in the very first VC the darkmode number (0-Auto; 1-On; 2-Off):
if darkmodeNumber == 0 {
if traitCollection.userInterfaceStyle == .light {
print("Light mode")
Colors.shared.setLightColors()
} else {
print("Dark mode")
Colors.shared.setDarkColors()
}
} else if darkmodeNumber == 1 {
Colors.shared.setDarkColors()
} else if modeNumber == 2 {
Colors.shared.setLightColors()
}
}
The statusbar should then change also the right way.
Use any system colors you like. They are all adaptive. I applied the system gray color to a button's text:
The color changes when we switch between light and dark mode.
I have custom colors within my code. I use them several times and I would like to have them allocated only once.
The situation / problem
If we get a look at UIColor headers we can see the following :
[...]
// Some convenience methods to create colors. These colors will be as calibrated as possible.
// These colors are cached.
open class var black: UIColor { get } // 0.0 white
open class var darkGray: UIColor { get } // 0.333 white
[...]
I've created an extension of UIColor, like so :
import UIKit
extension UIColor {
class func colorWithHexString(_ hex: String) -> UIColor {
print("\(#function): \(hex)")
// some code, then it return a UIColor
return UIColor(
red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
alpha: CGFloat(1.0)
)
}
// Option A
open class var myColorOne : UIColor {
get {
return colorWithHexString("AABBCC")
}
}
// Option B
class func myColorTwo() -> UIColor {
return colorWithHexString("DDEEFF")
}
}
From there I can use my colors easily, with either having a variable or a function.
// A
UIColor.myColorOne
// B
UIColor.myColorTwo()
Sadly, I'm not fully happy with that. Indeed, every time I want to use those colors : a new UIColor allocation is made.
What I've tried
Apple managed to make their color cached apparently. I would like to do so myself too. I've tried several things but none seems to be ideal.
1 - Using dispatch_once ✗
As visible on Swift page : the free function dispatch_once is no longer available in Swift.
2 - Creating a constant (let) ✗
I get the following error : extensions may not contain stored properties
3 - Creating a singleton ~
It does work (each color are created only once) with the following
import UIKit
class Colors : UIColor {
// Singleton
static let sharedInstance = Colors()
let myColorOne : UIColor = {
return UIColor.colorWithHexString("AABBCC")
}()
let myColorTwo : UIColor = {
return UIColor.colorWithHexString("DDEEFF")
}()
}
But it forces me to have one more file and call my colors like so
Colors.sharedInstance.myColorOne
Isn't there any way to get the colors I want like that UIColor.myColorOne and have them cached like Apple does ?
You can use the same approach as in
Using a dispatch_once singleton model in Swift, i.e. static
constant stored properties
which are initialized lazily (and only once). These can be defined
directly in the UIColor extension:
extension UIColor {
convenience init(hex: String) {
// ...
}
static let myColorOne = UIColor(hex:"AABBCC")
static let myColorTwo = UIColor(hex:"DDEEFF")
}
There might be a better way to do it, but using a global variable (like Grimxn mentioned in the comment) is one way to solve the problem.
Below is an example you can copy & paste into a playground:
import UIKit
extension UIColor {
class func colorWithHexString(_ hex: String) -> UIColor {
print("allocate color")
// do you conversion here...
return UIColor.black
}
}
private let myPrivateColorOne = UIColor.colorWithHexString("#ffffff")
extension UIColor {
open class var myColorOne: UIColor {
get {
print("get color")
return myPrivateColorOne
}
}
}
UIColor.myColorOne
UIColor.myColorOne
When you execute the code, the getter will be called twice, but colorWithHexString only once.
You could use your singleton to store the generated UIColor values as above and solve the Colors.sharedInstance.myColorOne naming problem by extending UIColor and putting the access in there:
extension UIColor {
class func myColorTwo() -> UIColor {
return Colors.sharedInstance.myColorTwo
}
}
In Swift 3:
extension UIColor {
class func color(hexString: String) -> UIColor {
// ...
}
static let myColorOne = color(hexString: "AABBCC")
}
Is there a way to set the UIView background color with Swift?
I know that in Objective-C, you would use self.view.backgroundColor = [UIColor redColor];, but that does not work the same way in Swift. I have looked around and because Swift is only about a week old, I cannot find an answer.
Does anyone have any suggestions?
self.view.backgroundColor = UIColor.redColor()
In Swift 3:
self.view.backgroundColor = UIColor.red
Try This, It worked like a charm! for me,
The simplest way to add backgroundColor programmatically by using ColorLiteral.
You need to add the property ColorLiteral, Xcode will prompt you with a whole list of colors in which you can choose any color. The advantage of doing this is we use lesser code, add HEX values or RGB. You will also get the recently used colors from the storyboard.
Follow steps ,
1) Add below line of code in viewDidLoad() ,
self.view.backgroundColor = ColorLiteral
and clicked on enter button .
2) Display square box next to =
3) When Clicked on Square Box Xcode will prompt you with a whole list of colors which you can choose any colors also you can set HEX values or RGB
4) You can successfully set the colors .
Hope this will help some one to set backgroundColor in different ways.
I see that this question is solved, but, I want to add some information than can help someone.
if you want use hex to set background color, I found this function and work:
func UIColorFromHex(rgbValue:UInt32, alpha:Double=1.0)->UIColor {
let red = CGFloat((rgbValue & 0xFF0000) >> 16)/256.0
let green = CGFloat((rgbValue & 0xFF00) >> 8)/256.0
let blue = CGFloat(rgbValue & 0xFF)/256.0
return UIColor(red:red, green:green, blue:blue, alpha:CGFloat(alpha))
}
I use this function as follows:
view.backgroundColor = UIColorFromHex(0x323232,alpha: 1)
some times you must use self:
self.view.backgroundColor = UIColorFromHex(0x323232,alpha: 1)
Well that was it, I hope it helps someone .
sorry for my bad english.
this work on iOS 7.1+
You can use the line below which goes into a closure (viewDidLoad, didLayOutSubViews, etc):
self.view.backgroundColor = .redColor()
EDIT Swift 3:
view.backgroundColor = .red
You can use this extension as an alternative if you're dealing with RGB value.
extension UIColor {
static func rgb(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor {
return UIColor(red: red/255, green: green/255, blue: blue/255, alpha: 1)
}
}
In Swift 4, just as simple as Swift 3:
self.view.backgroundColor = UIColor.brown
The response by #Miknash and #wolfgang gutierrez barrera was helpful to me. Only difference was I had to add rgbValue: to the function call.
UIColorFromHex(rgbValue: 0xA6D632,alpha: 1 ) like so
If you want to set your custom RGB color try this:
self.view.backgroundColor = UIColor(red: 20/255.0, green: 106/255.0, blue: 93/255.0, alpha: 1)
Don't forget to keep /255.0 for every color
In the Xcode 13, the shortcut ColorLiteral does not work anymore.
Now, you have to use this shortcut: #colorLiteral(
I'm trying to share my Scene Kit code across iOS and OS X, but the API calls that accept colors (and images) take either UIColor/UIImage or NSColor/NSImage depending on the platform. How do I create the right class in Swift without duplicating the code?
Use conditional compilation and type aliases:
#if os(OSX)
typealias Color = NSColor
typealias Image = NSImage
#else
typealias Color = UIColor
typealias Image = UIImage
#endif
Then use Color instead of UIColor or NSColor:
self.gameView!.backgroundColor = Color(red: 0, green: 0.2, blue: 0.5, alpha: 1)
Edit 2016-01-17: As DDPWNAGE noted above, Apple has created SKColor with basically the same definition.