iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
📝

Using UIFontPickerViewController in SwiftUI

に公開

First, let's wrap it.

FontPicker.swift
struct FontPicker: UIViewControllerRepresentable {
    let configuration: UIFontPickerViewController.Configuration
    @Binding var pickerResult: Font
    @Binding var isPresented: Bool

    func makeUIViewController(context: Context) -> UIFontPickerViewController {
        let controller = UIFontPickerViewController(configuration: configuration)
        controller.delegate = context.coordinator
        return controller
    }

    func updateUIViewController(_ uiViewController: UIFontPickerViewController, context: Context) {

    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UIFontPickerViewControllerDelegate {
        private let parent: FontPicker

        init(_ parent: FontPicker) {
            self.parent = parent
        }
        func fontPickerViewControllerDidPickFont(_ viewController: UIFontPickerViewController) {
            guard let descriptor = viewController.selectedFontDescriptor else { return }
            self.parent.pickerResult = Font.custom((descriptor.fontAttributes[.family] as? String) ?? descriptor.postscriptName, size: 16, relativeTo: .body)
            self.parent.isPresented = false
        }
    }
}

Now you just need to use it in your View.

ContentView.swift
struct FontPickView: View {
    @State private var isFontPickerPresented = false
    @State var selectedFont: Font = .body

    var fontPickerConfig: UIFontPickerViewController.Configuration {
        let config = UIFontPickerViewController.Configuration()
        config.displayUsingSystemFont = false
        config.includeFaces = true
        return config
    }

    var body: some View {
        VStack{
            Button{
                isFontPickerPresented = true
            } label: {
                Text("Select Font")
            }
            Text("Text テキスト").font(selectedFont)
        }
        .sheet(isPresented: $isFontPickerPresented){
            FontPicker(
                configuration: .init(),
                pickerResult: $selectedFont,
                isPresented: $isFontPickerPresented
            )
        }
    }
}

As a note of caution, fonts added by users via App Store apps or using .mobileconfig files cannot be selected with this alone. To verify this, you can use something like FontInstall.app.
https://fontinstall.app/
To make user-installed fonts available, you need to add a Capability.

Target > Signing & Capabilities > + Capability > Fonts

Add the Capability there and check Use Installed Fonts.
image
Building in this state will allow you to select fonts downloaded via FontInstall.app.

References

https://www.hackingwithswift.com/example-code/uikit/how-to-let-users-choose-a-font-with-uifontpickerviewcontroller
https://qiita.com/lcr/items/f9e98f76a48af0920bb1

Discussion