Where do you put a global method in swift? - ios

I have a function that is common to all my controllers:
func myColor() -> UIColor {
return UIColor(red: 9.0/255.0, green: 134.0/255.0, blue: 255.0/255.0, alpha: 1)
}
Where can I put this function, so I can access it from any controller?

By default all default access scope (internal) functions are available everywhere in the application. If you have this function defined in different module, you need to use public modifier.
To make your code clearer it is best to create extension for UIColor.
extension UIColor {
class func myColor() -> UIColor {
return UIColor(red: 9.0/255.0, green: 134.0/255.0, blue: 255.0/255.0, alpha: 1)
}
}
Then you can use myColor same way as default UIColor colors.
let systemColor = UIColor.blackColor()
let myColor = UIColor.myColor()

1) Is your function returning the same color every time as in the question? In that case why don't you make it a static color in AppDelegate which you can access anywhere using
(UIApplication.sharedApplication() as AppDelegate).myColor
2) If your color will return a different color everytime based on your class properties but uses the same formula for all classes for e.g.
func myColor() -> UIColor {
return UIColor(red: (prop1 * 5)/255.0, green: prop2/255.0, blue: (prop3/2)/255.0, alpha: 1)
}
you can define prop1,prop2,prop3 and the function in a base class which every class can override and set their own values for the properties. The function will not need to be overridden.
3) If the formula for calculating the color is different for every class, you can try making a protocol which defines this function and the properties. Every class which inherits from this property will have to provide their own implementation of the formula.
You can pick the appropriate solution based on your need.
I hope this helped!

Add a swift file name it UIColorExt.swift:
import UIKit
class func RGB(r: CGFloat, _ g: CGFloat, _ b: CGFloat, _ alpha: CGFloat = 1.0) -> UIColor{
return UIColor(red: r/255.0, green: g/255.0, blue: b/255.0, alpha: alpha)
}
Usage:
view.backgroundColor = UIColor.RGB(204, 119, 70)

Related

Unable to set custom colours to Navigation bar items iOS Swift

I am using the below code in my AppDelegate to set the colours for the Navigation Bar items. It works when I use the default colours (Step 1) and doesn't work when I use custom colours (Step 2).
Could someone please suggest how I could fix this ?
Step1: Works
// Set navigation bar, background color
UINavigationBar.appearance().barTintColor = UIColor.red
Step 2: Doesn't Work
// Set navigation bar, background color
UINavigationBar.appearance().barTintColor = UIColor(red: 41, green: 150, blue: 204, alpha: 1)
Here is my extension for my UIColor, implemented in one of my styles.swift file
extension UIColor {
convenience init(_ r: Double,_ g: Double,_ b: Double,_ a: Double) {
self.init(red: CGFloat(r/255), green: CGFloat(g/255), blue: CGFloat(b/255), alpha: CGFloat(a))
}
}
Try this
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)
}
}
Step 2 :
UINavigationBar.appearance().barTintColor = UIColor.rgb(41,150,204)
You are using the default initialiser and not the one implemented in the extension :
Remove the params in your code like so :
UINavigationBar.appearance().barTintColor = UIColor(41, 150, 204,1)
UIColor's init takes CGFloat parameters, and CGFloat is a typedef for Double. Try to change your extension to accept Int as parameters instead of Double
You are not actually correctly using your extension.
To use it, call like this,
UINavigationBar.appearance().barTintColor = UIColor(41,150,204,1)
When you use underscore _ character for method names in the method definition, you have to omit method names when calling it.
Your extension is wrong. You have to divide by a float. As of now you are dividing by an Int so you are probably just getting 0 or 1.
It should be "r/255.0" etc...
EDIT: And as others have pointed out, you are not using your extension.
It should be
UIColor(41, 150, 204, 1)
On your UIColor Extension, do you have a need to define a convenience init? or can't you just use:
public func rgba(_ r:Int, _ g:Int, _ b:Int, _ a:CGFloat) -> UIColor {
return UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: a)
}

Colors that will be used throughout an app or a class

I'm trying to improve my object oriented skills and I'm always debating if a class is needed or not.
I have a set of UIColors that I'm constantly using throughout my app in different ViewControllers, I originally started by adding them as constant globals as follow...
import UIKit
// Global COLORS
let myBlueColor = UIColor(red: 62.0/255, green: 174.0/255, blue: 206.0/255, alpha: 1.0)
// more global colors here...
class ViewController1{
// using my global color
myButton.layer.borderColor = myBlueColor.CGColor
}
// other viewController
import UIKit
class ViewController2{
// using my global color again
myButton2.layer.borderColor = myBlueColor.CGColor
}
But then I decided to created a class to force myself to think in more oriented way like so...
Color Class
import Foundation
import UIKit
class Color {
var myBlueColor:UIColor{
get{
return UIColor(red: 62.0/255, green: 174.0/255, blue: 206.0/255, alpha: 1.0)
}
}
var myLightGrayColor:UIColor{
get{
return UIColor(red: 249.0/255, green: 249.0/255, blue: 249.0/255, alpha: 1.0)
}
}
var myGreenColor:UIColor{
get{
return UIColor(red: 110.0/255, green: 186.0/255, blue: 64.0/255, alpha: 1.0)
}
}
var myRedColor:UIColor{
get{
return UIColor(red: 247.0/255, green: 118.0/255, blue: 113.0/255, alpha: 1.0)
}
}
var myYellowColor:UIColor{
get{
return UIColor(red: 255.0/255, green: 190.0/255, blue: 106.0/255, alpha: 1.0)
}
}
}
View Controller
import UIKit
class ViewController1{
private var myColor = Color()
// some other code here...
myButton.layer.borderColor = myBlueColor.CGColor
}
Other View Controller
import UIKit
class ViewController1{
private var myColor = Color()
// some other code here...
myButton2.layer.borderColor = myBlueColor.CGColor
}
Is my object oriented a better approach? Ok let me rephrase this, is this even how you would do it in a more object oriented way?
I don't know but my Color class looks weird by just using getters (computed properties).
Any suggestions to improve my code.
EDIT: Not a duplicate because I was interested on improving my object oriented example more than knowing if globals were ok to use.
Thanks
Definitely a good idea, but you can probably make it even more clear by just extending UIColor and making those all class functions, exactly the same way as the built-in UIColor.whiteColor(), etc.
You can do that like this:
extension UIColor {
class func peachColor() -> UIColor {
return UIColor(colorLiteralRed: 100.00 / 100.00, green: 92.9 / 100.0, blue: 65.9 / 100.0, alpha: 1.0)
}
...
}
Then, anywhere in your app, you can say UIColor.peachColor() and it'll work perfectly. These class extensions are a clean way to do it, and it'll allow you to avoid putting a var myColor = Color() in each view controller.
If you want to encapsulate your Colors in a class, and they will not change, the best way to do so in an OOP environment is by using public static final variables.
(My Swift is very rusty at best so this may be incorrect syntax but it should be clear nonetheless.)
final struct MyColors {
public static final blue:UIColor = UIColor(red: 62.0/255, green: 174.0/255, blue: 206.0/255, alpha: 1.0)
// etc
}
You can then reference the value by using MyColors.blue wherever you want, and that will refer to the single defined UIColor object.
Assuming that you're trying to theme your app globally with colors, you ought to look into Apple's Appearance API, UIAppearance.
For example, to set the default color of all UINavigationBars in your app, you would call:
UINavigationBar.appearance().tintColor = myColor
You can also set other appearance properties such as background images
For more info, see:
http://nshipster.com/uiappearance/
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIAppearance_Protocol/
https://gist.github.com/mattt/5135521

Using Extension for Converting Hex to UIColor [duplicate]

This question already has answers here:
How to use hex color values
(39 answers)
Closed 8 years ago.
I am trying to change the background color of TopScoreContainer to a lighter shade of green. I do not want to use greenColor() . Here is the line of code:
self.TopScoreContainer.backgroundColor = UIColor.greenColor()
Is it possible to substitute in a hexadecimal number or RGB value instead of greenColor() ? Thanks.
let myCustomColorHSBa = UIColor(hue: 120/360, saturation: 0.25 , brightness: 1.0 , alpha: 1)
let myCustomColorRGBa = UIColor(red: 191/255, green: 1, blue: 191/255, alpha: 1)
using it as an extension read-only computed var:
Read-Only Computed Properties
A computed property with a getter but no setter is known as a
read-only computed property. A read-only computed property always
returns a value, and can be accessed through dot syntax, but cannot be
set to a different value.
NOTE
You must declare computed properties—including read-only computed
properties—as variable properties with the var keyword, because their
value is not fixed. The let keyword is only used for constant
properties, to indicate that their values cannot be changed once they
are set as part of instance initialization.
You can simplify the declaration of a read-only computed property by
removing the get keyword and its braces:
extension UIColor {
var lightGreen: UIColor {
return UIColor(red: 191/255, green: 1, blue: 191/255, alpha: 1)
}
}
let lightGreen = UIColor().lightGreen
or you can also create your own htmlColor input as follow:
update: Xcode 7.2 • Swift 2.1.1
extension String {
subscript(range: Range<Int>) -> String {
return range.startIndex < 0 || range.endIndex > characters.count ? "Out of Range" : substringWithRange(Range(start: startIndex.advancedBy(range.startIndex),end: startIndex.advancedBy(range.endIndex)))
}
var hexaCGFloat: CGFloat {
return CGFloat(strtoul(self, nil, 16))
}
}
extension UIColor {
convenience init(htmlColor: String, alpha: Double) {
self.init(red: htmlColor[1...2].hexaCGFloat / 255.0, green: htmlColor[3...4].hexaCGFloat / 255.0, blue: htmlColor[5...6].hexaCGFloat / 255.0, alpha: CGFloat(alpha) )
}
convenience init(r: Int, g:Int , b:Int , a: Int) {
self.init(red: CGFloat(r)/255, green: CGFloat(g)/255, blue: CGFloat(b)/255, alpha: CGFloat(a)/255)
}
}
let myColor = UIColor(r: 255 , g: 0, b: 0, a: 255)
let myHtmlWebColor = UIColor(htmlColor: "#bfffbf", alpha: 1.0)

Add a custom palette to IB that propagates if a color changes iOS

I want to create a custom palette in IB where you can set colors, and if a color changes in that palette it propagates through the views. I've seen this approach http://natashatherobot.com/xcode-color-palette/, but if in the future, a color of the palette changes, you have to go to every view on the project and change that color. I tried also doing an #IBInspectable but you can't have enums (so you can map an enum to a color). I know i can just define the colors by code and then having an outlet, but the problem is I a have tons of views that I need to subclass just for changing a color like this:
class TestCommonView: CommonView {
#IBOutlet weak var borderView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
borderView.backgroundColor = Colors.fabrica.pastel
}
}
Any ideas?
Reconsidering this statement:
I tried also doing an #IBInspectable but you can't have enums (so you can map an enum to a color).
You can bridge over an #IBInspectable enum using Int this way:
enum ColorPalette:Int {
case clear = 0
case teal = 1
case plum = 2
case foam = 3
}
var tincture:ColorPalette = .clear
In code, access self.tincture, which is the enum you are after.
In Interface Builder, use tinctureAdapter which is an Int, and therefore a de-facto #IBInspectable of type enum.
// Stored IB property
#available(*, unavailable, message="Use tincture programmatically")
#IBInspectable var tinctureAdapter:Int {
get {
return self.tincture.rawValue
}
set {
self.tincture = ColorPalette:Int(rawValue: newValue) ?? .clear
}
}
It may be useful to place this code in a UIColor class Extension. Using the bridge approach, you could also use #Donamite plain-English strings in IB.
Swift 3 Example
#IBDesignable class ColorSwatchView: UIView {
enum ColorPalette: String {
case Thistle = "thistle"
case Plum = "plum"
case Olive = "olive"
case Iris = "iris"
case Clear = "clear"
}
let namedColors = [
"thistle": UIColor(red: 216/255, green: 191/255, blue: 216/255, alpha: 1),
"plum" : UIColor(red: 221/255, green: 160/255, blue: 221/255, alpha: 1),
"olive" : UIColor(red: 128/255, green: 128/255, blue: 0/255, alpha: 1),
"iris" : UIColor(red: 3/255, green: 180/255, blue: 200/255, alpha: 1)
]
var tincture:ColorPalette = .Clear
// Stored IB property
#available(*, unavailable, message: "Use tincture programmatically")
#IBInspectable var tinctureName: String? {
willSet {
if let color = ColorPalette(rawValue: newValue?.lowercased() ?? "") {
tincture = color
}
}
}
}
Interface Builder
Make your custom view a child of ColorSwatchView.
Programmatically
override func draw(_ rect: CGRect) {
let ctx = UIGraphicsGetCurrentContext()
ctx?.saveGState()
let uiColor = namedColors[tincture.rawValue] ?? UIColor.clear
ctx?.setFillColor(uiColor.cgColor)
ctx?.fill(bounds)
ctx?.restoreGState()
}
► Find this solution on GitHub and additional details on Swift Recipes.

How do I pick the color in hexadecimal form or RGB form instead of using the colors given to me in Swift [duplicate]

This question already has answers here:
How to use hex color values
(39 answers)
Closed 8 years ago.
I am trying to change the background color of TopScoreContainer to a lighter shade of green. I do not want to use greenColor() . Here is the line of code:
self.TopScoreContainer.backgroundColor = UIColor.greenColor()
Is it possible to substitute in a hexadecimal number or RGB value instead of greenColor() ? Thanks.
let myCustomColorHSBa = UIColor(hue: 120/360, saturation: 0.25 , brightness: 1.0 , alpha: 1)
let myCustomColorRGBa = UIColor(red: 191/255, green: 1, blue: 191/255, alpha: 1)
using it as an extension read-only computed var:
Read-Only Computed Properties
A computed property with a getter but no setter is known as a
read-only computed property. A read-only computed property always
returns a value, and can be accessed through dot syntax, but cannot be
set to a different value.
NOTE
You must declare computed properties—including read-only computed
properties—as variable properties with the var keyword, because their
value is not fixed. The let keyword is only used for constant
properties, to indicate that their values cannot be changed once they
are set as part of instance initialization.
You can simplify the declaration of a read-only computed property by
removing the get keyword and its braces:
extension UIColor {
var lightGreen: UIColor {
return UIColor(red: 191/255, green: 1, blue: 191/255, alpha: 1)
}
}
let lightGreen = UIColor().lightGreen
or you can also create your own htmlColor input as follow:
update: Xcode 7.2 • Swift 2.1.1
extension String {
subscript(range: Range<Int>) -> String {
return range.startIndex < 0 || range.endIndex > characters.count ? "Out of Range" : substringWithRange(Range(start: startIndex.advancedBy(range.startIndex),end: startIndex.advancedBy(range.endIndex)))
}
var hexaCGFloat: CGFloat {
return CGFloat(strtoul(self, nil, 16))
}
}
extension UIColor {
convenience init(htmlColor: String, alpha: Double) {
self.init(red: htmlColor[1...2].hexaCGFloat / 255.0, green: htmlColor[3...4].hexaCGFloat / 255.0, blue: htmlColor[5...6].hexaCGFloat / 255.0, alpha: CGFloat(alpha) )
}
convenience init(r: Int, g:Int , b:Int , a: Int) {
self.init(red: CGFloat(r)/255, green: CGFloat(g)/255, blue: CGFloat(b)/255, alpha: CGFloat(a)/255)
}
}
let myColor = UIColor(r: 255 , g: 0, b: 0, a: 255)
let myHtmlWebColor = UIColor(htmlColor: "#bfffbf", alpha: 1.0)

Resources