Search code examples
swiftenumsuikituibutton

Create a UIButton for each enum case in swift programmatically


I am trying to build a drawing app just for fun in swift UIKIt programmatically but now I just ran into a problem I am trying to create a palette of colors to swap UIColor properties, for that I have created an enum Pencil and made it CaseIterable to use .allCases iteration in a function so that I will be able to create a UIButton programmatically inside a createColorButton function but all i see is one single white square at the top of the simulator screen

this is my function

 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(buttonClicked), for: .touchUpInside)
            buttons.append(button)
        }
     return buttons
    }

ant this is 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 am passing that createColorButton function inside a secondViewController UIViewController but it does not work as I expected, as I mentioned. I only see one single "white square" instead of a UIbutton for each Pencil.color

    override func viewDidLoad() {
        super.viewDidLoad()
        
      
        let buttons = createColorButton()
        for button in buttons {
                self.view.addSubview(button)
            }
        setupImageViews()
        
    }

Any suggesting so I can make it work ?


Solution

  • As @HangerRash pointed out in their comment, you are putting all your buttons on top of each other and not adding any constraints to organize them.

    Try inserting all of your buttons into a vertical stack view. That will arrange them so that they are not all in the same position on the screen.

    (Alternatively you could create a set of auto layout anchors to size and space out the buttons.)

    I put your code into a Storyboard based project that contained a vertical UIStackView, pinned to the top, leading and trailing edges of it's parent view, and connected the stack view to an IBOutlet named stackView.

    I then modified your viewDidLoad() function like this:

        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
            }
        }
    

    And the results look like this:

    enter image description here