UIButton's backgroundImage's content mode not respected

The problem is that you add an image using setBackgroundImage() method. This adds your image to some private UIImageView that you can't reach directly like myButton.imageView!. In your code, you're applying contentType for you button instead of its background image.

If you want to reach this background UIImageView you need to use subviews array. But if you try to do this inside your viewDidLoad() method, you'll find that background UIImageView hasn't been added yet because your buttons layout method wasn't called. There are 2 ways to fix that.

Solution 1 – call layoutIfNeeded explicitly:

override func viewDidLoad() {
    super.viewDidLoad()

    myButton.setBackgroundImage(UIImage(named: "myImage"), for: .normal)
    myButton.layoutIfNeeded()
    myButton.subviews.first?.contentMode = .scaleAspectFit
}

Solution 2 – move contentMode setup at viewDidAppear method.

override func viewDidLoad() {
    super.viewDidLoad()

    myButton.setBackgroundImage(UIImage(named: "myImage"), for: .normal)
    myButton.setTitle("Some title", for: .normal)
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    myButton.subviews.first?.contentMode = .scaleAspectFit
}

Hope it helps you.


To simplify the accepted answer, all you need to do is layout the subviews and your setup code can be done in one place.

override func viewDidLoad() {
    super.viewDidLoad()

    myButton.setBackgroundImage(UIImage(named: "myImage.png"), for: .normal)
    myButton.layoutIfNeeded()
    myButton.subviews.first?.contentMode = .scaleAspectFill
}