manumateos.dev

Cómo usar fuentes personalizadas dentro de un paquete de Swift Package Manager

El proceso habitual para utilizar fuentes personalizadas en una aplicación de iOS implica añadirlas manualmente al fichero Info.plist, a un array con la clave UIAppFonts donde pondríamos todos los nombres de todos los ficheros que queramos usar, algo como JetBrainsMono-Regular.ttf. Pero la cosa cambia cuando lo que estás desarrollando está dentro de un paquete de Swift Package Manager; ahí no hay fichero donde meter las cosas.

El procedimiento es ligeramente distinto, pero se resume en:

  • Colocar los ficheros TTF/OTF en una carpeta. Esto seguro que ya lo habías hecho por tu cuenta. Dentro de Sources, en la carpeta que más rabia os dé.
  • Añadir la carpeta de recursos. En el/los target que vayan a utilizar estas fuentes tendrán que añadir esta carpeta a su array de recursos. Algo como:
.target(
    name: "App",
    dependencies: [...],
    resources: [
        .process("Resources/Fonts") // <==== ESTO
    ],
    linkerSettings: [
        ...
    ]),
  • Añadir código para registrar las fuentes. Esta parte es la que más difiere. He usado un código muy semejante al de Jacob Zivan, y lo he colocado en el mismo fichero donde defino mis fuentes (y, ahora que lo leo, quizá que sea estático no es la mejor de las ideas, pero ya investigaré sobre ello en otro momento):
static func registerFont(fontName: String) {
    guard let fontURL = Bundle.module.url(forResource: fontName, withExtension: "otf"),
            let fontDataProvider = CGDataProvider(url: fontURL as CFURL),
            let font = CGFont(fontDataProvider) else {
        fatalError("Error on registering \(fontName)")
    }
    var error: Unmanaged<CFError>?
    
    CTFontManagerRegisterGraphicsFont(font, &error)
}
  • Registrar las fuentes. Tenemos que crear un método que registre, una a una, cada una de las fuentes, con algo como Fonts.registerFont("JetBrainsMono-Regular"). En algún punto cercano al arranque de nuestra aplicación deberemos llamar a este método, para que de este modo podamos usar nuestras fuentes.

Recordad listar los nombres de cada tipografía para poder crear el objeto UIFont (o Font) con el nombre personalizado.

Esto se puede mejorar, por supuesto. Si creas un enumerado con todos los nombres de los ficheros sin extensión (y estos además coinciden con los nombres de las fuentes) puedes simplemente recorrer cada caso y además aprovechar el mismo enumerado para crear los objetos correspondientes.

Listar los nombres de las familias de cuentes

Este gist tiene cuatro líneas de código que funcionan de maravilla para averiguar los nomrbes que deberemos usar:

UIFont.familyNames.forEach({ familyName in
    let fontNames = UIFont.fontNames(forFamilyName: familyName)
    print(familyName, fontNames)
})