UIButton at your Convenience


UIButton is one of those classes where you have to take quite a few steps to set up an instance if you require anything beyond the default. For example, I would like to create a round button with a title, border, background colour, etc.
extension UIButton {
    convenience init(withRadius radius:CGFloat, title:String, titleColor:UIColor, target:UIViewController, selector:Selector, backgroundColor:UIColor, borderColor:UIColor, borderWidth:CGFloat, position:CGPoint) {
        self.init()
        self.setTitle(title, for: .normal)
        self.setTitleColor(titleColor, for: .normal)
        self.addTarget(target, action: selector, for: .touchDown)
        self.backgroundColor = backgroundColor
        let diameter = 2 * radius
        self.frame = CGRect(x: position.x, y: position.y, width: diameter, height: diameter)
        self.layer.cornerRadius = radius
        self.layer.masksToBounds = false
        self.layer.borderWidth = borderWidth
        self.layer.borderColor = borderColor.cgColor
    }
}
I'm avoiding hard coding sizes, colours, etc. because I want the code to be flexible but calling this initializer prevents me from forgetting to set any of the properties, so that instead of having to instantiate each button and then make adjustments, we can be all done in one line of code:
let button = UIButton(withRadius: 50, title: "My Button", titleColor: .white, target: self, selector: #selector(buttonTapped(sender:)), backgroundColor: .gray, borderColor: .gray, borderWidth: 1.0, position: CGPoint.zero)
We then need to simply add the button to our view:
view.addSubview(button)
And in this instance we also need the Selector that has been specified:
    @objc func buttonTapped(sender:AnyObject) {
        let but = sender as! UIButton
        if let col = but.backgroundColor {
            switch col {
            case  .gray:
                UIView.animate(withDuration: 0.75, animations: {
                    but.backgroundColor = .white
                    but.setTitleColor(.gray, for: .normal)
                })
                
            default:
                UIView.animate(withDuration: 0.75, animations: {
                    but.backgroundColor = .gray
                    but.setTitleColor(.white, for: .normal)
                })
            }}
    }

Why the convenience initializer?

It is logical to use a convenience initializer because we are instantiating the button from the initializer and then setting it up. You will also notice that if you attempt to create a designated initializer within a UIButton extension you will be informed by the compiler that this is not permitted.
Convenience initializers are secondary, supporting initializers for a class. You can define a convenience initializer to call a designated initializer from the same class as the convenience initializer with some of the designated initializer’s parameters set to default values. You can also define a convenience initializer to create an instance of that class for a specific use case or input value type. (The Swift Programming Language, Apple)

Comments