Noah Labhart
Noah Labhart

Reputation: 157

Swift UIButton override, setImage is not working

I'm trying to subclass UIButton with my own button class called FlipsSendButton. The code for this class is listed below. In it you can see that I am calling setImage to attempt to set the button image. However, after compiling, everything works correctly EXCEPT setting the image view.

Am I missing some steps in my code to set the image, or perhaps calling the optional and unwrap operators incorrectly?

import Foundation

class FlipSendButton : UIButton {

    let bgColor : UIColor

    init(frame aFrame: CGRect, bgColor aColor: UIColor) {
        bgColor = aColor;

        super.init(frame: aFrame)

        addTarget(self, action: Selector("buttonTouched:"), forControlEvents: .TouchUpInside)
        backgroundColor = aColor;

        setImage(UIImage(named: "flips.png") as UIImage?, forState: .Normal)
    }

    required init(coder aDecoder: NSCoder) {
        bgColor = UIColor.lightGrayColor()
        super.init(coder: aDecoder)
    }

    func buttonTouched(sender: UIButton) {
        if backgroundColor == UIColor.lightGrayColor() {
            backgroundColor = bgColor
        } else {
            backgroundColor = UIColor.lightGrayColor()
        }
    }
}

Also, it is worth mentioning that the image flips.png is in my images.xassets folder, if that makes a difference.

Upvotes: 2

Views: 5059

Answers (2)

Nir Golan
Nir Golan

Reputation: 1336

I found this frustrating as well. A fully functional UIButton subclass, that it's only flaw is setImage:. The easier solution I've found is writing a tiny helper class to set the image from outside:

class ButtonImageHelper {

    func setImage(image: UIImage?, forButton:UIButton) {
            forButton.setImage(image, forState: UIControlState.Normal)
    }   
}

This class can be positioned inside your UIButton subclass.
To call it:
ButtonImageHelper().setImage(yourImage, forButton:self)

Upvotes: 2

liushuaikobe
liushuaikobe

Reputation: 2190

You forgot the buttonType property. Besides, you'd better not subclass the UIButton(check out this for the reason).

Instead, You should set the buttonType property to UIButtonTypeCustom when you init the button, some sample code:

var myButton = UIButton.buttonWithType(.UIButtonTypeCustom)
myButton.setImage(UIImage(named: "flips.png") as UIImage?, forState: .Normal)

myButton.addTarget(self, action: Selector("buttonTouched:"), forControlEvents: .TouchUpInside)

func buttonTouched(sender: UIButton) {
    if sender.backgroundColor == UIColor.lightGrayColor() {
        sender.backgroundColor = bgColor
    } else {
        sender.backgroundColor = UIColor.lightGrayColor()
    }
}

-- EDIT --

If you want to reuse the style configuration, a better way is to define your own factory method of UIButton. Something like:

import Foundation
import UIKit
import ObjectiveC

private var bgColorKey: UInt8 = 0

extension UIButton {

    var bgColor: UIColor {
        get {
            return objc_getAssociatedObject(self, &bgColorKey) as! UIColor
        }
        set (neewColor) {
            objc_setAssociatedObject(self, &bgColorKey, neewColor, .OBJC_ASSOCIATION_RETAIN)
        }
    }

    class func buttonWithFrame(f: CGRect, backgroundColor color: UIColor) -> UIButton {
        let button = UIButton(type: .Custom)
        button.frame = f
        button.backgroundColor = color;
        button.bgColor = color
        button.setImage(UIImage(named: "flips.png") as UIImage?, forState: .Normal)
        button.addTarget(button, action: "buttonTouched:", forControlEvents: .TouchUpInside)
        return button
    }

    func buttonTouched(sender: UIButton) {
        if sender.backgroundColor == UIColor.lightGrayColor() {
            sender.backgroundColor = sender.bgColor
        } else {
            sender.backgroundColor = UIColor.lightGrayColor()
        }
    }
}

Then you can use the button like:

var btn = UIButton.buttonWithFrame(CGRectMake(50, 50, 100, 50), backgroundColor: UIColor.greenColor())
self.view.addSubview(btn)

Upvotes: 9

Related Questions