from - uicolor hexadecimal swift
¿Cómo agregar inicializadores en extensiones a las clases UIKit existentes, como UIColor? (3)
Bueno, si realmente, realmente, realmente quieres anular un inicializador, hay una manera.
Antes de seguir leyendo : nunca hagas esto para cambiar el comportamiento de UIKit
. ¿Por qué? Podría confundir a alguien que no puede entender por qué un inicializador UIColor
no está haciendo lo que normalmente hace. Solo hazlo para corregir un error de UIKit
, o agrega funcionalidad, etc.
He usado lo siguiente para parchear varios errores de iOS.
Código
extension UIColor {
private static var needsToOverrideInit = true
override open class func initialize() {
// Only run once - otherwise subclasses will call this too. Not obvious.
if needsToOverrideInit {
let defaultInit = class_getInstanceMethod(UIColor.self, #selector(UIColor.init(red:green:blue:alpha:)))
let ourInit = class_getInstanceMethod(UIViewController.self, #selector(UIColor.init(_red:_green:_blue:_alpha:)))
method_exchangeImplementations(defaultInit, ourInit)
needsToOverrideInit = false
}
}
convenience init(_red: CGFloat, _green: CGFloat, _blue: CGFloat, _alpha: CGFloat) {
// This is trippy. We swapped implementations... won''t recurse.
self.init(red: _red, green: _green, blue: _blue, alpha: _alpha)
///////////////////////////
// Add custom logic here //
///////////////////////////
}
}
Explicación
Esto está utilizando la naturaleza dinámica de Objective-C, llamada desde Swift, para intercambiar los punteros de definición de método en tiempo de ejecución. Si no sabe lo que esto significa, o sus implicaciones, probablemente sea una buena idea leer sobre el tema antes de usar este código.
La documentación de Swift dice que es posible agregar inicializadores en una extensión, y el ejemplo en el documento es acerca de agregar un inicializador a una estructura . Xcode no reconoce el inicializador designado de UIColor
en mi inicializador de conveniencia:
extension UIColor {
convenience init(rawValue red: CGFloat, green g: CGFloat, blue b: CGFloat, alpha a: CGFloat) {
// Can not find out the designated initializer here
self.init()
}
}
¿Alguna solución?
Cambiar los tipos de parámetros también funcionará.
extension UIColor {
convenience init(red: Int, green: Int, blue: Int, alpha: CGFloat) {
let normalizedRed = CGFloat(red) / 255
let normalizedGreen = CGFloat(green) / 255
let normalizedBlue = CGFloat(blue) / 255
self.init(red: normalizedRed, green: normalizedGreen, blue: normalizedBlue, alpha: alpha)
}
}
Uso
let newColor: UIColor = UIColor.init(red: 74, green: 74, blue: 74, alpha: 1)
Por lo general, olvidaría el trabajo redundante de dividir los valores de los componentes por 255. Así que hice este método para facilitarme.
No puede hacerlo de esta manera, debe elegir diferentes nombres de parámetros para crear sus propios inicializadores de la siguiente manera:
extension UIColor {
convenience init(r: UInt8, g: UInt8 , b: UInt8 , a: UInt8) {
self.init(red: CGFloat(r)/255, green: CGFloat(g)/255, blue: CGFloat(b)/255, alpha: CGFloat(a)/255)
}
convenience init(r: Double, g: Double , b: Double , alpha: Double) {
self.init(red: CGFloat(r), green: CGFloat(g), blue: CGFloat(b), alpha: CGFloat(alpha))
}
}
let myGreenColor1 = UIColor(r: 0, g: 255, b: 0, a: 255)
let myGreenColor2 = UIColor(r: 0, g: 1, b: 0, alpha: 1)