为整个 iOS 应用程序 swift 使用自定义字体

Using custom font for entire iOS app swift

我知道要在屏幕上设置元素的自定义字体我可以简单地做到someLabel.font=UIFont(name: "Exo 2.0", size: 15)

我想知道如何使用 swift 为整个应用程序设置它。 (一个 hack 是对应用程序的每个元素执行我所知道的操作,但这将成为可维护性的噩梦)

我看到这个问题已经用 objective-C 标签问过,How to set a custom font for entire iOS app without specifying size 但我对 objective-C 不够熟悉,无法将代码移植到 swift

您可以设置 UILabel 和其他 UIView 的外观:

UILabel.appearance().font = UIFont(name: "yourFont", size: yourSize)

更一般:

AnyUIView.appearance().font = UIFont(name: "yourFont", size: yourSize)

作为更详细的答案和这些好处,我建议使用扩展:

  • 无大小覆盖(无论您在设计器中设置什么都会被使用)
  • 无样式覆盖(我的代码中实现了粗体、浅体、中体、超细体,但您可以根据需要自定义)
import UIKit

extension UILabel {
    @objc var substituteFontName : String {
        get {
            return self.font.fontName;
        }
        set {
            let fontNameToTest = self.font.fontName.lowercased();
            var fontName = newValue;
            if fontNameToTest.range(of: "bold") != nil {
                fontName += "-Bold";
            } else if fontNameToTest.range(of: "medium") != nil {
                fontName += "-Medium";
            } else if fontNameToTest.range(of: "light") != nil {
                fontName += "-Light";
            } else if fontNameToTest.range(of: "ultralight") != nil {
                fontName += "-UltraLight";
            }
            self.font = UIFont(name: fontName, size: self.font.pointSize)
        }
    }
}

extension UITextView {
    @objc var substituteFontName : String {
        get {
            return self.font?.fontName ?? "";
        }
        set {
            let fontNameToTest = self.font?.fontName.lowercased() ?? "";
            var fontName = newValue;
            if fontNameToTest.range(of: "bold") != nil {
                fontName += "-Bold";
            } else if fontNameToTest.range(of: "medium") != nil {
                fontName += "-Medium";
            } else if fontNameToTest.range(of: "light") != nil {
                fontName += "-Light";
            } else if fontNameToTest.range(of: "ultralight") != nil {
                fontName += "-UltraLight";
            }
            self.font = UIFont(name: fontName, size: self.font?.pointSize ?? 17)
        }
    }
}

extension UITextField {
    @objc var substituteFontName : String {
        get {
            return self.font?.fontName ?? "";
        }
        set {
            let fontNameToTest = self.font?.fontName.lowercased() ?? "";
            var fontName = newValue;
            if fontNameToTest.range(of: "bold") != nil {
                fontName += "-Bold";
            } else if fontNameToTest.range(of: "medium") != nil {
                fontName += "-Medium";
            } else if fontNameToTest.range(of: "light") != nil {
                fontName += "-Light";
            } else if fontNameToTest.range(of: "ultralight") != nil {
                fontName += "-UltraLight";
            }
            self.font = UIFont(name: fontName, size: self.font?.pointSize ?? 17)
        }
    }
}

使用扩展的示例:

例如将这些行放在您的起始控制器 viewDidLoad

UILabel.appearance().substituteFontName = "IRANSans"; // USE YOUR FONT NAME INSTEAD
UITextView.appearance().substituteFontName = "IRANSans"; // USE YOUR FONT NAME INSTEAD
UITextField.appearance().substituteFontName = "IRANSans"; // USE YOUR FONT NAME INSTEAD

P.S。正如@Christian 提到的,您几乎可以为 AnyUIView

编写自己的扩展

我在 Swift 4 和 iOS 11

中找到了相同的方法

只需要在变量名前加上@objc关键字即可。 所以变量声明会像这样

@objc public var substituteFontName : String {
    get {}
    set {}
}

希望这对面临此问题的其他人有所帮助。

终于想通了。我能找到的最干净的方法。 (Swift 4) 解决方案不需要您设置字体大小,也不会覆盖所有字体大小。

  UILabel.appearance().font = UIFont.preferredFont(forTextStyle: UIFontTextStyle(rawValue: "Roboto"))

对于寻找此代码放置位置的用户。我把它放在我的 AppDelegate.swift 文件里面

 func application(_ application: UIApplication, 
 didFinishLaunchingWithOptions...

Swift 4.2

 UILabel.appearance().font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle(rawValue: "Roboto"))

答案是已经提供的答案的组合,但我必须尝试组合才能让它在 iOS 13 中工作:

这一切都放在 Table View Controller 中,它符合 UIFontPickerViewControllerDelegate 以便为用户提供选择字体的视图。 这将使用新字体更新所有 UILabel,但保留其他属性。

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let cell = tableView.cellForRow(at: indexPath)

    if cell === fontCell {
        if #available(iOS 13, *) {
            let configuration = UIFontPickerViewController.Configuration()
            configuration.includeFaces = true

            let fontVC = UIFontPickerViewController(configuration: configuration)
            fontVC.delegate = self

            present(fontVC, animated: true)
        } else {
            let ac = UIAlertController(title: "iOS 13 is required", message: "Custom fonts are only supported by devices running iOS 13 or above.", preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default))
            present(ac, animated: true)
        }
    }
}

}

@available(iOS 13.0, *)
extension AppearanceTableViewController: UIFontPickerViewControllerDelegate {
    func fontPickerViewControllerDidPickFont(_ viewController: UIFontPickerViewController) {
        // attempt to read the selected font descriptor, but exit quietly if that fails
        guard let descriptor = viewController.selectedFontDescriptor else { return }

        let font = UIFont(descriptor: descriptor, size: 20)
        UILabel.appearance().substituteFontName = font.fontName
    }
}

extension UILabel {
    @objc public var substituteFontName : String {
        get {
            return self.font.fontName;
        }
        set {
            let fontNameToTest = self.font.fontName.lowercased()
            var fontName = newValue
            if fontNameToTest.range(of: "bold") != nil {
                fontName += "-Bold"
            } else if fontNameToTest.range(of: "medium") != nil {
                fontName += "-Medium"
            } else if fontNameToTest.range(of: "light") != nil {
                fontName += "-Light"
            } else if fontNameToTest.range(of: "ultralight") != nil {
                fontName += "-UltraLight"
            }
            self.font = UIFont(name: fontName, size: self.font.pointSize)
        }
    }
}