skip to Main Content

I won’t get to into the weeds on what my app is ultimately doing but the issue I’m having is when I click on one of 6 button that all have a UIImage in their imageView I then try to reference the image name (the images are coming from my assets) to switch over which button was pressed and use the results to update a label.

The values are being set and printing out in the action, however the switch statement always falls through to default and I can’t figure out why. Are the button imageViews effecting the image names?

@IBOutlet var feelingLabel: UILabel!

var feelingImage: UIImage? {
    didSet {
        switch feelingImage {
        case UIImage(named: "happyFace"):
            self.feelingLabel.text = "feeling happy"
        case UIImage(named: "fineFace"):
            self.feelingLabel.text = "feeling fine"
        case UIImage(named: "angryFace"):
            self.feelingLabel.text = "feeling angry"
        case UIImage(named: "anxiousFace"):
            self.feelingLabel.text = "feeling anxious"
        case UIImage(named: "sadFace"):
            self.feelingLabel.text = "feeling sad"
        case UIImage(named: "sickFace"):
            self.feelingLabel.text = "feeling sick"
        default:
            self.feelingLabel.text = "feeling..."
        }
    }
}

// all six buttons are connected to this action 
@IBAction func feelingButtonTapped(_ sender: UIButton) {
    guard let selectedFeelingImage = sender.imageView?.image,
          selectedFeelingImage != self.feelingImage else {
        self.feelingImage = nil
        return
    }
    self.feelingImage = selectedFeelingImage
    print(selectedFeelingImage)
    print(self.feelingImage)
}

2

Answers


  1. If you want to compare images, you need to convert them to Data as following:

    var feelingImage: UIImage? {
    didSet {
        switch feelingImage!.pngData() {
        case UIImage(named: "happyFace")!.pngData():
            self.feelingLabel.text = "feeling happy"
        case UIImage(named: "fineFace")!.pngData():
            self.feelingLabel.text = "feeling fine"
        case UIImage(named: "angryFace")!.pngData():
            self.feelingLabel.text = "feeling angry"
        case UIImage(named: "anxiousFace")!.pngData():
            self.feelingLabel.text = "feeling anxious"
        case UIImage(named: "sadFace")!.pngData():
            self.feelingLabel.text = "feeling sad"
        case UIImage(named: "sickFace")!.pngData():
            self.feelingLabel.text = "feeling sick"
        default:
            self.feelingLabel.text = "feeling..."
        }
    }
    

    }

    Login or Signup to reply.
  2. A UIImage does not have a "name" … your image resource does, and that’s what you are using to load the image. However, once it is loaded, there is no association with the resource name.

    While comparing the .pngData may work, it would be a very inefficient approach.

    One very good approach would be to track your buttons in an array, and use the array index to determine which button was tapped.

    Another approach would be to subclass UIButton and add your own .imageName property.

    For example:

    class NamedButton: UIButton {
        var imageName: String = ""
    }
    

    Now, in code, your button creating becomes:

        if let img = UIImage(named: "happyFace") {
            let btn = NamedButton()
            btn.setImage(img, for: [])
            btn.imageName = "happyFace"
            btn.addTarget(self, action: #selector(feelingButtonTapped(_:)), for: .touchUpInside)
        }
    

    your "current selection" can be:

    var feelingImageName: String = "" {
        
        didSet {
            switch feelingImageName {
            case "happyFace":
                self.feelingLabel.text = "feeling happy"
            case "fineFace":
                self.feelingLabel.text = "feeling fine"
            case "angryFace":
                self.feelingLabel.text = "feeling angry"
            case "anxiousFace":
                self.feelingLabel.text = "feeling anxious"
            case "sadFace":
                self.feelingLabel.text = "feeling sad"
            case "sickFace":
                self.feelingLabel.text = "feeling sick"
            default:
                self.feelingLabel.text = "feeling..."
            }
        }
    
    }
    

    and your button action can be:

    @IBAction func feelingButtonTapped(_ sender: UIButton) {
        
        guard let btn = sender as? NamedButton,
              btn.imageName != self.feelingImageName else {
            self.feelingImageName = ""
            return
        }
        self.feelingImageName = btn.imageName
        print(btn.imageName)
        print(self.feelingImageName)
    
    }
    

    If you are using Storyboard / Interface Builder for your layout, you can make the .imageName property @IBInspectable so you can set it at design-time:

    class NamedButton: UIButton {
        @IBInspectable var imageName: String = ""
    }
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search