UIFont.pointSize is an immutable, get-only property. To change the font size of a UILabel, create a new UIFont instance using label.font = label.font.withSize(20) or use UIFont.systemFont(ofSize:weight:) to set the exact size and weight.When modifying text styling on iOS, attempting to assign a new value directly to label.font.pointSize triggers a Swift compiler error: Cannot assign to property: 'pointSize' is a get-only property. Because UIFont instances are immutable objects in UIKit, you cannot update individual typographic properties in place.
Here is why this error occurs and how to properly adjust font sizes on a UILabel across modern versions of iOS while preserving font families, weights, and Dynamic Type scaling.
Why this happens
In UIKit, UIFont is designed as an immutable value representation of an underlying typography face. Properties such as pointSize, familyName, fontName, and capHeight describe structural characteristics of that specific font representation. None of these properties expose a public setter.
When you access label.font, you receive a reference to an immutable UIFont object. Swift enforces value safety and immutability rules at compile time. Because pointSize has no setter, writing label.font.pointSize = 24.0 causes the compiler to reject the statement immediately.
To alter the size of a label’s text, you must instantiate a new UIFont object with your desired dimensions and assign that entire font instance back to the label’s font property.
How to fix it
Depending on whether your label uses standard system typography, custom font files, or Dynamic Type, choose the approach that best fits your interface architecture.
1. Use withSize() to derive a new font
If you want to keep the existing font family already assigned to the label (whether set in a storyboard or in code), call withSize(_:) on the current font:
import UIKit
final class ProfileViewController: UIViewController {
@IBOutlet private weak var titleLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Derives a new font instance with point size 22.0
titleLabel.font = titleLabel.font.withSize(22.0)
}
}
withSize(_:) returns a copy of the receiver’s font descriptor adjusted to the specified point size.
Important caveat: On certain system fonts, invoking withSize(_:) on a styled or custom-weighted font (like Medium or Semibold) can sometimes fall back to the Regular font weight. If preserving specific traits is essential, consider using font descriptors or explicit system font declarations.
2. Preserve font weights using UIFontDescriptor
To ensure bold, semibold, or italic traits are preserved when resizing an arbitrary font, extract its fontDescriptor and generate the new UIFont through that descriptor:
import UIKit
extension UILabel {
func updateFontSize(to size: CGFloat) {
guard let currentFont = font else { return }
let descriptor = currentFont.fontDescriptor
font = UIFont(descriptor: descriptor, size: size)
}
}
// Usage:
headlineLabel.updateFontSize(to: 28.0)
This method keeps all custom symbolic traits—such as traitBold or traitItalic—intact without resetting the typographic styling back to standard regular weight.
3. Assign an explicit system font
If your label uses Apple’s standard system typography (San Francisco), you can directly assign a system font configured with your exact size and weight:
// Standard regular weight
label.font = UIFont.systemFont(ofSize: 18.0)
// Specific weight (Bold, Semibold, Light, etc.)
label.font = UIFont.systemFont(ofSize: 20.0, weight: .semibold)
// Italic or Bold shortcuts
label.font = UIFont.boldSystemFont(ofSize: 24.0)
label.font = UIFont.italicSystemFont(ofSize: 16.0)
This is often the cleanest solution for programmatic UIKit layouts, as it makes both the size and weight intention clear in a single line of code.
4. Support Dynamic Type with UIFontMetrics
Hardcoded point sizes do not scale when users adjust their preferred text size in iOS Settings. If your app supports accessibility scaling with custom sizes, wrap your font in UIFontMetrics:
import UIKit
final class ArticleViewController: UIViewController {
private let summaryLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
let baseFont = UIFont.systemFont(ofSize: 17.0, weight: .regular)
summaryLabel.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: baseFont)
summaryLabel.adjustsFontForContentSizeCategory = true
}
}
By enabling adjustsFontForContentSizeCategory, the label automatically scales its text dynamically when the system content size category changes, respecting the user’s accessibility preferences.
5. Update custom PostScript fonts by name
If your project utilizes bundled custom fonts (such as OpenType or TrueType assets), create the replacement font using the font’s PostScript name:
if let customFont = UIFont(name: "AvenirNext-DemiBold", size: 21.0) {
label.font = customFont
} else {
// Fallback if the font name is mistyped or missing
label.font = UIFont.systemFont(ofSize: 21.0, weight: .semibold)
}
Ensure that custom font files are declared under the UIAppFonts (Fonts provided by application) key in your project’s Info.plist and included in the target’s Copy Bundle Resources build phase.
How to prevent it
- Treat typography objects as immutable: Always create and assign a new
UIFontinstead of attempting to mutate individual properties on existing instances. - Use text styles over fixed sizes: Adopt
UIFont.preferredFont(forTextStyle:)wherever possible to support Dynamic Type automatically without manual point-size calculations. - Avoid resizing in layout loops: Do not reassign
label.fontinsideviewDidLayoutSubviews()orlayoutSubviews()unless necessary, as modifying fonts triggers text recalculations and invalidates intrinsic content sizes. - Use convenience extensions: Add a project-wide extension on
UILabelto standardize how sizes and weights are updated across programmatic views.
FAQ
Can I change only the font size of an NSAttributedString?
Yes, but you must apply .font attributes across the string’s character range using NSMutableAttributedString. You can retrieve the existing font attribute, invoke withSize(_:) on it, and reapply it to the attributed string using addAttribute(_:value:range:).
Why did my label lose its bold style after calling withSize()?
Calling withSize(_:) directly on system fonts created with .boldSystemFont or specific weights can cause UIKit to drop the symbolic trait descriptor. To retain weight traits, instantiate the replacement font via UIFont(descriptor: label.font.fontDescriptor, size: newSize) or call UIFont.systemFont(ofSize:weight:).
Does changing the font size automatically update the label’s frame?
If you are using Auto Layout, modifying label.font automatically invalidates its intrinsicContentSize, causing the layout engine to recalculate the frame. If you use manual frame-based layout, you must call label.sizeToFit() or update the frame manually after altering the font size.
Parts of this guide are adapted from content licensed under CC BY-SA 4.0; this article is shared under the same license.
