skip to Main Content

I’m going to make a numPad using stackView
this is my code

private func setKeypadButton(num: Int) -> UIButton {
    let button = UIButton()
    button.setTitle(String(num), for: .normal)
    button.titleLabel?.font = .systemFont(ofSize: 50)
    button.setTitleColor(.black, for: .normal)
    button.frame.size = CGSize(width: 60, height: 60)
    button.tapPublisher
        .sink {
            guard let num = button.titleLabel?.text else { return }
            print(num)
        }.store(in: &subscription)
    
    return button
}

private func setKeypad() {
    let keypadHorizontalStackView = UIStackView()
    keypadHorizontalStackView.axis = .horizontal
    keypadHorizontalStackView.spacing = 0
    for i in 1...9 {
        let button = setKeypadButton(num: i)
        keypadHorizontalStackView.addArrangedSubview(button)
        if i % 3 == 0 {
            keypadVerticalStackView.addArrangedSubview(keypadHorizontalStackView)
            keypadHorizontalStackView.arrangedSubviews.forEach {
                keypadHorizontalStackView.removeArrangedSubview($0)
            }
        }
    }
}

SetKeypad function is executed in viewDidLoad
I expect the view to come out like this

123
456
789

But my buttons overlap in the z-direction

view

What am I missing?

2

Answers


  1. Chosen as BEST ANSWER

    UIStackView is a reference type Therefore, when removingArrangedSubView, the views in the verticalStackView are also removed

    So I changed it like this, and it works fine

    private func setKeypad() {
        var count = 1
        for _ in 0..<3 {
            let keypadHorizontalStackView = UIStackView()
            keypadHorizontalStackView.axis = .horizontal
            keypadHorizontalStackView.spacing = 0
            keypadHorizontalStackView.distribution = .fillEqually
            
            for _ in 0..<3 {
                let button = setKeypadButton(num: count)
                keypadHorizontalStackView.addArrangedSubview(button)
                count += 1
            }
            keypadVerticalStackView.addArrangedSubview(keypadHorizontalStackView)
        }
    }
    

  2. First this method .removeArrangedSubview doesn’t remove provided view from stack’s subview array, therefore the view is still display as a part of view hierarchy, that why you see your button overlap in z-direction. You should use view.removeFromSuperview if you want to remove view from superview. You can read about removeArrangedSubview here

    Second stackView is a class, so it’s reference type. So this line keypadVerticalStackView.addArrangedSubview(keypadHorizontalStackView) just add the same horizontal stack view to your vertical stack view and its not correct solution.

    If I want to make UI display as your expectation, i will do something like

    let horizontalStackViews = [UIStackView(), UIStackView(), UIStackView()]
        horizontalStackViews.forEach { (stackView) in
            stackView.axis = .horizontal
            stackView.spacing = 0
            stackView.distribution = .equalSpacing
            verticalStackView.addArrangedSubview(stackView)
        }
        var row = 0
        var number = 1
        repeat {
            horizontalStackViews[row].addArrangedSubview(setKeypadButton(num: number))
            number += 1
            if number % 3 == 1 { row += 1 }
        } while row < 3
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search