SF Symbols配合约束使用时尺寸不符合预期的技术问题咨询
I’ve run into this exact issue before—SF Symbols don’t always map directly to a font’s point size when using textStyle in the configuration. Here’s why you’re seeing that 33.33pt size instead of the expected 28pt, and how to fix it:
Why the Discrepancy?
When you use SymbolConfiguration(textStyle: .title1), SF Symbols scales the symbol to match the line height of the text style, not just the font’s point size. Text styles include extra vertical spacing (for ascenders/descenders and line height) that makes the symbol’s canvas larger than the raw point size. That’s why your symbol ends up at 33.33pt instead of the 28pt point size of .title1.
Solution 1: Directly Set the Symbol’s Point Size
The simplest fix is to bypass the text style configuration and explicitly set the symbol’s point size to match your .title1 font size. This ensures the symbol’s dimensions align exactly with the font’s point size:
// Get the exact point size of the title1 font let title1PointSize = UIFont.preferredFont(forTextStyle: .title1).pointSize // Create a configuration using the point size directly let symbolConfig = UIImage.SymbolConfiguration(pointSize: title1PointSize, weight: .regular) // Generate your symbol image with this configuration let chevronImage = UIImage(systemName: "chevron.left", withConfiguration: symbolConfig)? .withTintColor(UIColor.TextColor!) .withRenderingMode(.alwaysOriginal)
With this setup, your symbol will render at exactly 28pt (or whatever the current .title1 point size is), and your getSize() method will return the correct dimensions for your button constraints.
Solution 2: Scale the Symbol to Target Size (If You Need Text Style)
If you still want to use the text style (for dynamic type support, for example), you can manually scale the symbol to your desired size after generating it:
let title1PointSize = UIFont.preferredFont(forTextStyle: .title1).pointSize let targetSize = CGSize(width: title1PointSize, height: title1PointSize) // Generate the symbol with text style configuration first let textStyleConfig = UIImage.SymbolConfiguration(textStyle: .title1) guard let originalSymbol = UIImage(systemName: "chevron.left", withConfiguration: textStyleConfig)? .withTintColor(UIColor.TextColor!) .withRenderingMode(.alwaysOriginal) else { // Handle nil case return } // Render the symbol into the target size let renderer = UIGraphicsImageRenderer(size: targetSize) let scaledSymbol = renderer.image { context in originalSymbol.draw(in: CGRect(origin: .zero, size: targetSize)) }
This will force the symbol to fit exactly into your 28pt size while retaining any dynamic type behavior from the text style.
Notes on Your Current Setup
- Your
getSize()method returns the image view’s size, which is based on the symbol’s original canvas size (the 33.33pt one) when using text style. Basing your button constraints on this will make the button larger than intended. contentMode = .scaleAspectFitwon’t shrink the symbol to 28pt—it just ensures the symbol fits within the image view’s bounds (which are tied to the oversized symbol size). Fixing the symbol’s source size is the root solution here.
内容的提问来源于stack exchange,提问作者Steven James

