skip to Main Content

Trying to add a UIView that fills the screen, that works fine. But I also want to add a UIButton to the bottom of the UIView, but somehow the UIButton doesn’t show up:

let screenSize: CGRect = UIScreen.main.bounds
let myView = UIView(frame: CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height))
myView.backgroundColor = .systemGray5.withAlphaComponent(0.5)
        
let button = UIButton()
button.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: 40)
button.setTitle("Sleeping.. Tap here to wake up!", for: UIControl.State.normal)
button.translatesAutoresizingMaskIntoConstraints = false
        
button.frame.origin = CGPoint(x:0, y:self.view.frame.size.height - button.frame.size.height - 20)
        
myView.addSubview(button)
        
self.view.addSubview(myView)

EDIT from answer:

I get error message on line:

button.bottomAnchor.constraint(equalTo: myView.bottomAnchor, constant: 10).isActive = true

Error message:

libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x600002658c40 "UIButton:0x7f8dce6146c0'Sleeping.. Tap here to wa...'.bottom"> and <NSLayoutYAxisAnchor:0x600002658a80 "UIView:0x7f8dce613080.bottom"> because they have no common ancestor.  Does the constraint or its anchors reference items in different view hierarchies?  That's illegal.'
terminating with uncaught exception of type NSException
CoreSimulator 857.7 - Device: iPhone 14 Pro (1B903119-D288-4E1C-B36B-F8B7A44AA0DE) - Runtime: iOS 16.0 (20A360) - DeviceType: iPhone 14 Pro
(Recorded stack frame) 

3

Answers


  1. You have to add constraints to your button. For general guides, you can take a look into this SO answer. But for your purpose, adding 2 anchor constraints like this should do the trick:

    let screenSize: CGRect = UIScreen.main.bounds
    let myView = UIView(frame: CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height))
    myView.backgroundColor = .systemGray5.withAlphaComponent(0.5)
            
    let button = UIButton()
    button.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: 40)
    button.setTitle("Sleeping.. Tap here to wake up!", for: UIControl.State.normal)
    button.bottomAnchor.constraint(equalTo: myView.bottomAnchor, constant: 10).isActive = true
    button.centerYAnchor.constraint(equalTo: myView.centerYAnchor).isActive = true
    button.translatesAutoresizingMaskIntoConstraints = false
            
    button.frame.origin = CGPoint(x:0, y:self.view.frame.size.height - button.frame.size.height - 20)
            
    myView.addSubview(button)
            
    self.view.addSubview(myView)
    
    Login or Signup to reply.
  2. try this
    button.bottomAnchor.constraint(equalTo: myView.bottomAnchor, constant: 10).isActive = true this code add in override func viewDidAppear(_ animated: Bool) or after
    (about swift life cycle)

    I hope this helps you.

    Login or Signup to reply.
  3. It’s probably because of the constrain, I would recommend you using constrain instead of using rect like that, since the xib or storyboard already have their own view, you don’t need to create screenSize like that, my suggestion for you is that try to use constrain instead for every view or button that you want to create, it would be great, readable and maintainable if you write something like this

    let containerView = UIView()
    let actionButton = UIButton()
    
    actionButton.setTitle("Sleeping.. Tap here to wake up!", for: .normal)
    
    view.addSubview(containerView)
    containerView.addSubview(actionButton)
    
    containerView.translatesAutoresizingMaskIntoConstraints = false
    actionButton.translatesAutoresizingMaskIntoConstraints = false
    
    NSLayoutConstraint.activate([
      containerView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
      containerView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
      containerView.topAnchor.constraint(equalTo: self.view.topAnchor),
      containerView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
      
      actionButton.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -10.0),
      actionButton.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 10.0),
      actionButton.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -10.0),
      actionButton.heightAnchor.constraint(equalToConstant: 50.0)
    ])
    

    The code above actually show the same result like what you wrote, but in safer way.

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