skip to Main Content

I followed Hacking With Swift’s Project 2 and I had very obscure (i.e. I have no clue what’s going on) issues with Interface Builder.

I’ve built the layout as described in the tutorial:

  • 3 buttons, constrained to be separated by 30px from each other
  • each button contains an image of a flag
  • each button is 200×100 in size

When I run Resolve AutoLayout Issues, all buttons get resized to 224×114 and get a padding which can’t be removed by using Interface Builder (all insets are set to 0 and button’s content mode is set to scale to fit). This can only be resolved by applying padding by code:

button1.configuration?.contentInsets = NSDirectionalEdgeInsets.zero
button2.configuration?.contentInsets = NSDirectionalEdgeInsets.zero
button3.configuration?.contentInsets = NSDirectionalEdgeInsets.zero

I’ve compared my Storyboard with the code in HWS repository, but didn’t notice anything different.

Here is the full code:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var button1: UIButton!
    @IBOutlet weak var button2: UIButton!
    @IBOutlet weak var button3: UIButton!
    
    var countries = [String]()
    var correctAnswer = 0
    var answeredQuestions = 0
    var score = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        countries += [
            "estonia", "france", "germany", "ireland",
            "italy", "monaco", "nigeria", "poland",
            "russia", "spain", "uk", "us"
        ]
        
        button1.configuration?.contentInsets = NSDirectionalEdgeInsets.zero
        button2.configuration?.contentInsets = NSDirectionalEdgeInsets.zero
        button3.configuration?.contentInsets = NSDirectionalEdgeInsets.zero
        
        button1.layer.borderWidth = 1
        button2.layer.borderWidth = 1
        button3.layer.borderWidth = 1
        button1.layer.borderColor = UIColor.lightGray.cgColor
        button2.layer.borderColor = UIColor.lightGray.cgColor
        button3.layer.borderColor = UIColor.lightGray.cgColor
        
        askQuestion()
    }
    
    func askQuestion(action: UIAlertAction! = nil) {
        countries.shuffle()
        
        correctAnswer = Int.random(in: 0...2)
        let answer = countries[correctAnswer].uppercased()
        title = "(answer) – score: (score)"
        
        button1.setImage(UIImage(named: countries[0]), for: .normal)
        button2.setImage(UIImage(named: countries[1]), for: .normal)
        button3.setImage(UIImage(named: countries[2]), for: .normal)
    }

    @IBAction func buttonTapped(_ sender: UIButton) {
        var title: String
        var message: String
        var buttonText: String
        
        answeredQuestions += 1
        
        if (sender.tag == correctAnswer) {
            title = "Correct"
            score += 1
        } else {
            let answer = countries[correctAnswer].uppercased()
            title = "Wrong! That's the flag of (answer)"
            score -= 1
        }
        
        if (answeredQuestions >= 10) {
            message =  "Your final score is (score)."
            buttonText = "Restart"
            answeredQuestions = 0
            score = 0
        } else {
            message =  "Your score is (score)."
            buttonText = "Continue"
        }
        
        
        let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: buttonText, style: .default, handler: askQuestion))
        present(ac, animated: true)
    }
}

That’s how my Buttons are set up in IB:
IB's size inspector

IB's attribute inspector

IB's constraints

2

Answers


  1. Two things….

    First comment: this is likely being caused by the new Button style. If you change it from Plain to Default:

    enter image description here enter image description here

    IB should keep the size at 200 x 100.

    Second comment: it’s a much better idea to assign constraints exactly as you want them rather than relying on IB’s "automatically fix the layout."

    Login or Signup to reply.
  2. In iOS 15, the UIButton.Configuration API was added, and this added a few more options to IB, as well as changes to how buttons look. The tutorial was likely written before this, and did not take this into account.

    Currently, every button you add in IB will by default use a UIButton.Configuration. This is what gives it the insets, which is part of the default configuration. In addition to setting this in code, it can also be set in IB under "Background Configuration":

    enter image description here

    If you don’t want to use a configuration, and instead want the pre-iOS 15 behaviour, change "Style" to "Default":

    enter image description here

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