How to add initializers in extensions to existing UIKit classes such as UIColor?

后端 未结 3 1931
花落未央
花落未央 2021-02-06 23:39

The Swift documentation says that adding initializers in an extension is possible, and the example in the document is about adding an initializer to a struct. Xcode doe

3条回答
  •  忘掉有多难
    2021-02-07 00:11

    Well, if you really, really, really want to override an initialiser, there is a way.

    Before you read further: never do this to change UIKit behaviour. Why? It could confuse the heck out of someone that can't figure out why a UIColor initialiser isn't doing what it normally does. Only do it to fix a UIKit bug, or add functionality, etc.

    I have used the following to patch several iOS bugs.

    Code

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

    Explanation

    This is using the dynamic nature of Objective-C, called from Swift, to swap method definition pointers at runtime. If you don't know what this means, or implications of it, it is probably a good idea to read up on the topic before you use this code.

提交回复
热议问题