Search code examples
swiftxcodeibdesignable

How To Create A Re-usable IBDesignable Code


When using IBDesignable, the following code is common and I end up repeating every time I create a class, is there a way to avoid this repetition?

override init(frame: CGRect) {
    super.init(frame: frame)

    themeProp()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    themeProp()
}

override func prepareForInterfaceBuilder() {
    super.prepareForInterfaceBuilder()

    themeProp()
}

This is how I am currently using IBDesignable to create styles for UIButton.

import UIKit

let colorWhite = colorLiteral(red: 0.9999127984, green: 1, blue: 0.9998814464, alpha: 1)
let colorLavender = colorLiteral(red: 0.6604440808, green: 0.5388858914, blue: 0.8827161193, alpha: 1)

@IBDesignable class PrimaryButtonA: UIButton {

    override init(frame: CGRect) {
        super.init(frame: frame)

        themeProp()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        themeProp()
    }

    func themeProp() {
        setTitleColor(colorWhite, for:.normal)
        self.layer.cornerRadius = 10
        backgroundColor = colorLavender
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()

        themeProp()
    }
}


@IBDesignable class PrimaryButtonB: UIButton {

    override init(frame: CGRect) {
        super.init(frame: frame)

        themeProp()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        themeProp()
    }

    func themeProp() {
        setTitleColor(colorWhite, for:.normal)
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()

        themeProp()
    }
}

With my limited knowledge, I tried to create a function and tried calling it inside each class but it doesn't work.

It doesn't make any sense to repeat this 12 lines of code in every class declaration. So, if there is a way to avoid this repetition then please use my code for the answer.

Thanks!


Solution

  • A possible solution is creating a common superclass for these views. The only disadvantage is that you have to create a superclass for each type (UIViews, UIButtons etc.)

    class DesignableView: UIView {
        override init(frame: CGRect) {  
            super.init(frame: frame)  
            themeProp()  
        }  
    
        required init?(coder aDecoder: NSCoder) {  
            super.init(coder: aDecoder)  
            themeProp()  
        }  
    
        override func prepareForInterfaceBuilder() {  
            super.prepareForInterfaceBuilder()  
            themeProp()  
        }
    
        func themeProp() { }
    }
    

    After that, make your designable class a subclass of DesignableView. You will only have to override themeProp() in that.