SwiftUIで NavigationViewのタイトルにカスタムフォントが反映されない

NavigationViewのタイトルには Text() を指定できるが、タイトルに対して font Modifierを設定してもカスタムフォントが反映されなかった。

実行環境

  • Xcode 11.6
  • iOS 13.6

問題の挙動

あらかじめFontクラスでカスタムフォントを返す拡張メソッドを追加した。

import SwiftUI

extension Font {
    
    static func futuraMedium(size: CGFloat) -> Font {
        return Font.custom("Futura-Medium", size: size)
    }
}

NavigationViewのタイトルには Text() を指定できるが、下記のように設定してもタイトル部分のフォントは変わらない。

NavigationView {
    VStack {
        Text("ねこ")
    }
    .navigationViewStyle(StackNavigationViewStyle())
    .navigationBarTitle(Text(R.string.localizable.home_title()).font(.futuraMedium(size: 30)), displayMode: .inline)
}

カスタムフォントだからダメなのか?システムフォントに変えてみてもフォントサイズは反映されない。

NavigationView {
    VStack {
        Text("ねこ")
    }
    .navigationViewStyle(StackNavigationViewStyle())
    .navigationBarTitle(Text(R.string.localizable.home_title()).font(.system(size: 30)), displayMode: .inline)
}

デフォルトの大きさのままに見える。

f:id:ch3cooh393:20200721221425p:plain

解決編

UIKit用のUIFontの拡張メソッドを用意した。

import UIKit

extension UIFont {
    
    static func futuraMediumFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: "Futura-Medium", size: size) ?? UIFont.systemFont(ofSize: size, weight: .medium)
    }
}

Stack Overflowの記事を参考にして、ブリッジ用のクラスを作成する。

struct NavigationBarBuilder: UIViewControllerRepresentable {

    var build: (UINavigationController) -> Void = { _ in }

    func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationBarBuilder>) -> UIViewController {

        UIViewController()
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationBarBuilder>) {

        if let navigationController = uiViewController.navigationController{
            self.build(navigationController)
        }
    }
}

利用時に下記のように [NSAttributedString.Key:Any] でカスタムフォントを指定する。

import SwiftUI

struct HomeView : View {

    var body: some View {
        NavigationView {
            VStack {
                Text("ねこ")
                Spacer()
            }
            .navigationViewStyle(StackNavigationViewStyle())
            .navigationBarTitle(Text(R.string.localizable.home_title()), displayMode: .inline)
            .background(NavigationBarBuilder { nc in
                nc.navigationBar.titleTextAttributes = [ .font: UIFont.futuraMediumFont(ofSize: 22) ]
            })
        }
    }
}

実行するとカスタムフォントが表示される。

f:id:ch3cooh393:20200721224218p:plain

参考記事