如何在现有UIKit类(如UIColor)的扩展中添加初始值设定项?

时间:2015-01-11 05:51:11

标签: swift uicolor

Swift文档说可以在扩展中添加初始化程序,文档中的示例是关于向 struct 添加初始化程序。 Xcode在我的便利初始化程序中无法识别UIColor指定的初始化程序:

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()

  }
}

任何解决方案?

3 个答案:

答案 0 :(得分:31)

你不能这样做,你必须选择不同的参数名来创建你自己的初始化器,如下所示:

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)

答案 1 :(得分:2)

好吧,如果你真的,真的,真的想要覆盖初始化者,那就有办法了。

在您进一步阅读之前:永远不要这样做更改 UIKit行为。为什么?它可能会让那些能够弄清楚UIColor初始化者没有做正常事情的人的混淆。只做它来修复UIKit错误或添加功能等。

我使用以下内容修补了几个iOS错误。

代码

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 // 
        ///////////////////////////         

    }

}

说明

这是使用从Swift调用的Objective-C的动态特性来在运行时交换方法定义指针。如果您不知道这意味着什么,或者它的含义,在您使用此代码之前阅读该主题可能是一个好主意。

答案 2 :(得分:1)

更改参数类型也可以。

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)
    }
}

<强>用法

let newColor: UIColor = UIColor.init(red: 74, green: 74, blue: 74, alpha: 1)

我通常会忘记将组件值除以255的冗余工作。所以我使用这种方法来方便我。