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()
}
}
解決策はありますか?
次のように独自のイニシャライザーを作成するには、このようにはできません。別のパラメーター名を選択する必要があります。
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)
まあ、本当に、本当に、本当に初期化子をオーバーライドしたい場合は、方法があります。
さらに読む前に:これをchangeUIKit
の動作にしないでください。どうして? 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の動的な性質を使用して、実行時にメソッド定義ポインターを交換します。これが何を意味するのか、またはその意味がわからない場合は、このコードを使用する前にトピックを読むことをお勧めします。
パラメータタイプの変更も機能します。
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で割るという冗長な作業を忘れてしまいます。そのため、私はこの方法を使って自分を容易にしました。