'Why does UIButton.setTitle change the font size?

I'm building an iOS app for a class, and I'm following along some instructions. The Edit button is connected to toggleEditingMode, but when I change the text, for some reason the font size is reset to 17, even though it's 30 in the storyboard editor.

I've tried changing the font size, if I print the current font size after executing setTitle it still says 30, so it seems like it must be happening outside of setTitle, but it only triggers if I use setTitle. Help!

class ItemsViewController: UITableViewController {
    var choreStore: ChoreStore!
    var roommateStore: RoommateStore!
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return choreStore.allChores.count
    }
        
    override func tableView(_ tableView: UITableView,
            cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // Create an instance of UITableViewCell with default appearance
        let cell = tableView.dequeueReusableCell(withIdentifier: "chore", for: indexPath) as! ChoreCell

        // Set the text on the cell with the description of the item
        // that is at the nth index of items, where n = row this cell
        // will appear in on the table view
        let chore = choreStore.allChores[indexPath.row]

        cell.title?.text = chore.title
        cell.turn?.text = "\(chore.whoseTurn())'s Turn"
        cell.completed?.text = chore.completedString()
        cell.completed?.textColor = chore.isOverdue ? .red : .black

        return cell
    }
    
    @IBAction func addNewItem(_ sender: UIButton) {

    }

    @IBAction func toggleEditingMode(_ sender: UIButton) {
        setEditing(!isEditing, animated: true)
        sender.setTitle(isEditing ? "Done" : "Edit", for: .normal)
    }
}


Solution 1:[1]

Change your button style to Default:

Setting style

Solution 2:[2]

Your question is relatively vague but based on my interpretation this should fix your font size issue. I haven't read the documentation on this but my guess is whenever you use .setTitle it creates a completely new UILabel thus all the properties set in Story Board are no longer used because you've disposed of the original label.

@IBAction func toggleEditingMode(_ sender: UIButton) {
        setEditing(!isEditing, animated: true)
        sender.setTitle(isEditing ? "Done" : "Edit", for: .normal)
        //Set the font size after setting title
        sender.titleLabel?.font = UIFont.systemFont(ofSize: 30.0) 

    }

For custom fonts:

@IBAction func toggleEditingMode(_ sender: UIButton) {
        setEditing(!isEditing, animated: true)
        sender.setTitle(isEditing ? "Done" : "Edit", for: .normal)
        //Set the font size after setting title
        sender.titleLabel?.font = UIFont(name:"fontname", size: 30.0) 

    }

Solution 3:[3]

There are various approaches to setting a UIButton's title text:

   1.  myButton.setTitle("Some Title", for: .normal)

   2.  myButton.titleLabel?.text = "Some Title"

   3.  myButton.setAttributedTitle(attrString, for: .normal)

The first approach discards the previous label and creates a new one with a default font and characteristics.

The second approach re-uses the previous label of the "currentTitle" property, retaining the font, size and label characteristics. However, it's fragile. For example, pressing the button could cause the text and font to change out from underneath you.

The better supported way to set a font for the title for each button state in a persistent way is to use UIButton API's:

func setAttributedTitle(NSAttributedString?, for: UIControl.State)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jeremy Caney
Solution 2
Solution 3