Search code examples
iosswiftuikituilabeluistackview

Update a label's text in a UIStackView and while keeping the text centered?


When I place a label with centered text in a stack view, then update the text, it no longer appears centered.

import PlaygroundSupport
import UIKit

let stackView = UIStackView(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 20)))

let label = UILabel(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 20)))
label.text = "Hello"
label.textAlignment = .center

stackView.addArrangedSubview(label)

label.text = "World"

PlaygroundPage.current.liveView = stackView

The expected outcome is that "World" is centered. However, it appears leftaligned. Calling layoutSubviews() did not help.


Solution

  • Stack views don't play well without auto-layout - particularly in Playgrounds.

    Try it like this:

    import UIKit
    import PlaygroundSupport
    
    class MyViewController : UIViewController {
        override func loadView() {
            let view = UIView()
    
            view.backgroundColor = .white
    
            let stackView = UIStackView()
            
            let label = UILabel()
            label.text = "Hello"
            label.textAlignment = .center
    
            // so we can see the frame
            label.backgroundColor = .green
            
            stackView.addArrangedSubview(label)
            
            label.text = "World"
    
            view.addSubview(stackView)
            
            stackView.translatesAutoresizingMaskIntoConstraints = false
            
            NSLayoutConstraint.activate([
                stackView.widthAnchor.constraint(equalToConstant: 100.0),
                stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20.0),
            ])
            
            self.view = view
        }
    }
    
    // Present the view controller in the Live View window
    PlaygroundPage.current.liveView = MyViewController()