You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部分字体无法应用到SwiftUI特定视图的问题求助

SwiftUI中EnvironmentObject字体切换部分字体不生效问题

在SwiftUI项目中,基于EnvironmentObject实现了字体切换功能:设置菜单内的所有内置及第三方字体均可正常渲染,但在PostView等其他视图中,部分字体(如Trebuchet、Roboto等)无法生效。已确认EnvironmentObject已注入根视图,调试打印显示字体名称正确传递,但问题仍存在。

最小复现示例(仅使用内置字体)

@main
struct FontExampleApp: App {
    @StateObject private var appearanceManager = AppearanceManager()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appearanceManager)

        }
    }
}

class AppearanceManager: ObservableObject {

    @Published var Font: String = "System" {
        didSet {
            saveFont()
            objectWillChange.send()
            print("Set font to \(Font)")
            print("Corresponding font name: \(fonts[Font])")
        }
    }
    
    public let fonts = ["System" : "system-default", // unrecognized name defaults to system font
                        "Times New Roman" : "TimesNewRomanPSMT",
                        "Trebuchet" : "TrebuchetMS"
    ]
    
    init() {
        loadFont()
        
        for family in UIFont.familyNames.sorted() {
            let names = UIFont.fontNames(forFamilyName: family)
            print("Family: \(family) Font names: \(names)")
        }
    }
    
    private let fontKey = "FontKey"
    
    private func saveFont() {
        UserDefaults.standard.set(Font, forKey: fontKey)
    }
    
    private func loadFont() {
        if let savedFont = UserDefaults.standard.value(forKey: fontKey) as? String {
            Font = savedFont
        }
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            PostView()
            Spacer()
            FontSelectionView()
        }
        .padding()
    }
}


struct PostView: View {
    @EnvironmentObject var appearanceManager: AppearanceManager
    
    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 16) {
                Text("Hello World")
                // below only works for certain fonts
                    .font(.custom(appearanceManager.Font, size: 30, relativeTo: .title))
                
            }
            .padding()
        }
    }
}

struct FontSelectionView: View {
    @EnvironmentObject var appearanceManager: AppearanceManager

    var body: some View {
        Section(header: Text("Fonts")) {
            VStack(alignment: .leading) {
                ForEach(appearanceManager.fonts.keys.sorted(), id: \.self) { fontName in
                    FontButton(name: fontName)
                }
                .padding(.vertical, 5)
            }
        }
    }
}

struct FontButton: View {
    @EnvironmentObject var appearanceManager: AppearanceManager

    let name: String
    var isSelected: Bool {
        appearanceManager.Font == name
    }

    var body: some View {
        HStack {
            Text(name)
                .font(.custom(appearanceManager.fonts[name] ?? "", size: 17, relativeTo: .body))
            Spacer()
            Circle()
                .frame(width: 20, height: 20)
                .foregroundColor(isSelected ? .secondary : .clear)
                .overlay(
                    Circle()
                        .stroke(Color.primary, lineWidth: 2)
                )
        }
        .foregroundColor(.secondary)
        .onTapGesture {
            withAnimation {
                appearanceManager.Font = name
            }
        }
    }
}

该示例中Times New Roman可正常生效,但Trebuchet无法应用到PostView的文本上。

调试打印信息

添加第三方字体后,设置菜单内所有字体均可正常显示,但PostView等视图仍存在部分字体无法生效的问题,调试打印显示字体名称已正确传递:

// 初始化时打印的字体信息
...
Family: Times New Roman Font names: ["TimesNewRomanPSMT", "TimesNewRomanPS-ItalicMT", "TimesNewRomanPS-BoldMT", "TimesNewRomanPS-BoldItalicMT"]
Family: Trebuchet MS Font names: ["TrebuchetMS", "TrebuchetMS-Italic", "TrebuchetMS-Bold", "Trebuchet-BoldItalic"]
Family: Ubuntu Mono Font names: ["UbuntuMono-Regular"]
...

// 切换字体时的打印
Set font to Trebuchet
Corresponding font name: Optional("TrebuchetMS") // 未在设置菜单外生效

Set font to JetBrains Mono
Corresponding font name: Optional("JetBrainsMono-Regular") // 正常生效

Set font to Roboto
Corresponding font name: Optional("RobotoMono-Regular") // 未在设置菜单外生效

内容的提问来源于stack exchange,提问作者John Harrington

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 16:56:12