Search code examples
iosswiftuibuttoninterface-builderibdesignable

How to show image on custom button control in designer


I have a custom button control where I am trying to show an image for the button but it is not appearing despite defining it programatically.

@IBDesignable class UCButtonNext: UIButton {
    // setup programatically
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupButton()
    }

    // setup via Storyboard
    required init?(coder aDecoder: NSCoder) {
        //fatalError("init(coder:) has not been implemented")
        super.init(coder: aDecoder)
        setupButton()
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        setupButton()
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        setupButton()
    }

    func setupButton() {
        setupButtonStyle()
        setupShadow()
    }

    func setupButtonStyle() {
        setTitleColor(.white, for: .normal)

        backgroundColor         = UIColor.clear
        titleLabel?.font        = UIFont(name: "Courier", size: 18)
        setTitleColor(UIColor.black, for: .normal)

        layer.cornerRadius      = frame.height / 2
        layer.borderWidth       = 1.0
        layer.borderColor       = UIColor.white.cgColor

        setImage(UIImage(named: "btnArrowRight"), for: .normal)
    }

My button shows in designer but can't seem to get the image to show.

enter image description here


Solution

  • The answer Alex pointed you to - https://stackoverflow.com/a/40359161/10657724 - should be what you need.

    To help you debug the problem, change this line:

    setImage(UIImage(named: "btnArrowRight"), for: .normal)
    

    to:

        // DYNAMIC BUNDLE DEFINITION FOR DESIGNABLE CLASS
        let dynamicBundle = Bundle(for: type(of: self))
    
        // AND THEN SUCCESSFULLY YOU CAN LOAD THE RESSOURCE
        if let image = UIImage(named: "btnArrowRight", in: dynamicBundle, compatibleWith: nil) {
            setImage(image, for: .normal)
            setTitle("Works!", for: .normal)
        } else {
            setTitle("Failed!", for: .normal)
        }
    

    That will set the title of your button to either "Works!" or "Failed!"

    If you see "Works!" you should also see your image.

    Otherwise, you've got something wrong with your image resource.