Search code examples
swiftuikituibuttonaddtarget

UIButton will not work in UIKit programmatically


I have been building a drawing app programmatically in swift UIKit. I have been able to create UIButtons for each case that I have defined inside a Pencil enum. I can see each button appear for each Pencil.color. My problem is that I have created a @obj function called buttonClicked that should assign the color that correspond to each button but when I click it, it does not work does not even print in the console that click event is detected.

Here is the variables that hold the properties of my pencil brush:

 var lastPoint = CGPoint.zero
    var color = UIColor.black
    var brushWidth: CGFloat = 10.0
    var opacity: CGFloat = 1.0
    var swiped = false

this my buttonClicked function that assigns each color:

  @objc func buttonClicked(_ sender: UIButton){
        guard let pencil = Pencil(tag: sender.tag) else {
          return
        }
        
        color = pencil.color
     
        if pencil == .eraser {
          opacity = 1.0
        }
        print("button Clicked")
    }

The function that creates the button for each Pencil.color

    func createColorButton() -> [UIButton]{
        
        var buttons: [UIButton] = []
        for pencilCase in Pencil.allCases {
            let button = UIButton(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
            button.backgroundColor = pencilCase.color
            button.tag = pencilCase.hashValue
            button.addTarget(self, action: #selector(self.buttonClicked(_:)), for: .touchUpInside)

            buttons.append(button)
        }
     return buttons
    }

and just to give context here is a reference of my Pencil enum

enum Pencil: CaseIterable {
    
    case black
    case grey
    case red
    case darkblue
    case lightBlue
    case darkGreen
    case lightGreen
    case brown
    case orange
    case yellow
    case eraser
    
    init?(tag: Int) {
        switch tag {
        case 1:
          self = .black
        case 2:
          self = .grey
        case 3:
          self = .red
        case 4:
          self = .darkblue
        case 5:
          self = .lightBlue
        case 6:
          self = .darkGreen
        case 7:
          self = .lightGreen
        case 8:
          self = .brown
        case 9:
          self = .orange
        case 10:
          self = .yellow
        case 11:
          self = .eraser
        default:
          return nil
        }
      }
    // cases for penil.color 
    var color: UIColor {
      switch self {
      case .black:
        return .black
      case .grey:
        return UIColor(white: 105/255.0, alpha: 1.0)
      case .red:
        return UIColor(red: 1, green: 0, blue: 0, alpha: 1.0)
      case .darkblue:
        return UIColor(red: 0, green: 0, blue: 1, alpha: 1.0)
      case .lightBlue:
        return UIColor(red: 51/255.0, green: 204/255.0, blue: 1, alpha: 1.0)
      case .darkGreen:
        return UIColor(red: 102/255.0, green: 204/255.0, blue: 0, alpha: 1.0)
      case .lightGreen:
        return UIColor(red: 102/255.0, green: 1, blue: 0, alpha: 1.0)
      case .brown:
        return UIColor(red: 160/255.0, green: 82/255.0, blue: 45/255.0, alpha: 1.0)
      case .orange:
        return UIColor(red: 1, green: 102/255.0, blue: 0, alpha: 1.0)
      case .yellow:
        return UIColor(red: 1, green: 1, blue: 0, alpha: 1.0)
      case .eraser:
        return .white
      }
    }
}

I tried to call the addTarget inside viewDidLoad but that did not work either so here is the first version of my code

override func viewDidLoad() {
        super.viewDidLoad()
        
      
        let buttons = createColorButton()
        stackView.spacing = 5
        for button in buttons {
            stackView.addArrangedSubview(button)
                       button.layer.borderWidth = 1
                       button.layer.borderColor = UIColor.blue.cgColor
            
                       button.layer.cornerRadius = 10
                
            }
        view.addSubview(stackView)
        NSLayoutConstraint.activate([
            stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 200)
            ])
        
        setupImageViews()
        
    }

What else could I try to do to make the createColorButton work?


Solution

  • There are various ways to work with enums ... for your case, it's easy to use Pencil.allCases.enumerated() and set the button tag to the index:

    class ColorButtonsVC: UIViewController {
        
        var color: UIColor = .white
        var opacity: CGFloat = 1.0
    
        let cLabel = UILabel()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            
            let buttons = createColorButton()
            let stackView = UIStackView()
            stackView.spacing = 5
            for button in buttons {
                stackView.addArrangedSubview(button)
                button.layer.borderWidth = 1
                button.layer.borderColor = UIColor.blue.cgColor
                
                button.layer.cornerRadius = 10
                
            }
            stackView.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(stackView)
            NSLayoutConstraint.activate([
                stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 200),
                stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            ])
            
            cLabel.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(cLabel)
            NSLayoutConstraint.activate([
                cLabel.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 8.0),
                cLabel.widthAnchor.constraint(equalToConstant: 200.0),
                cLabel.heightAnchor.constraint(equalToConstant: 60.0),
                cLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            ])
            cLabel.text = "Color"
            cLabel.textAlignment = .center
            //setupImageViews()
            
        }
        
        func createColorButton() -> [UIButton]{
            var buttons: [UIButton] = []
            for (idx, pencilCase) in Pencil.allCases.enumerated() {
                let button = UIButton(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
                button.backgroundColor = pencilCase.color
                // the Pencil enum starts at 1 instead of Zero
                //  so add 1 to the index
                button.tag = idx + 1
                button.addTarget(self, action: #selector(self.buttonClicked(_:)), for: .touchUpInside)
                buttons.append(button)
            }
            return buttons
        }
        
        @objc func buttonClicked(_ sender: UIButton){
    
            guard let pencil = Pencil(tag: sender.tag) else {
                return
            }
            
            color = pencil.color
            
            if pencil == .eraser {
                opacity = 1.0
            }
            print("button Clicked:", sender.tag)
            
            cLabel.backgroundColor = color
        }
    }