【问题标题】:Using custom font for entire iOS app swift为整个 iOS 应用快速使用自定义字体
【发布时间】:2015-03-26 15:44:58
【问题描述】:

我知道要在屏幕上设置元素的自定义字体,我可以简单地做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 扩展,返回你想要的字体来代替它的内部字体属性。

标签: ios swift fonts


【解决方案1】:

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

  • 没有尺寸覆盖(将使用您在设计器中设置的任何内容)
  • 没有样式覆盖(在我的代码中实现了粗体、浅色、中等、超轻,但您可以根据需要对其进行自定义)
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

附:正如@Christian 提到的,您几乎可以为 AnyUIView 编写自己的扩展

【讨论】:

  • 这仍然适用于 iOS 11 和 swift 4 吗? UILabel 中的 self.font.fontName 得到 nil
  • 我会检查并尽快通知您结果
  • 谢谢,有空请留言
  • 更新:你必须将@objc 添加到substituteFontName 以保持与swift4的兼容性
  • 如何使用相同的概念全局替换属性文本字体?
【解决方案2】:

答案是已经提供的答案的组合,但我必须尝试多种方法才能使其在 iOS 13 中运行:

这一切都放在一个表格视图控制器中,它符合 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)
        }
    }
}

【讨论】:

    【解决方案3】:

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

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

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

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

    斯威夫特 4.2

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

    【讨论】:

    • @DanielBeltrami 你可以把它放在你的应用程序委托中...... func application(_ application: UIApplication, didFinishLaunchingWithOptions 它应该在应用程序范围内工作
    • 似乎不适用于带有 Swift 4.2 的 iOS 12,大多数文本的字体大小都变小了。
    • 当然是didFinishLaunchingWithOptions。但没关系,我找到了更好的解决方案来更改整个应用程序的字体:stackoverflow.com/a/40484460/8157190
    • 不起作用。覆盖标签上的所有字体大小。迅速 5.
    • 答案清楚地说明了swift 4.2。所以不起作用,如果您不是在谈论相同的版本@spnkr,这实际上不是正确的回应
    【解决方案4】:

    我在 Swift 4 和 iOS 11

    中找到了同样的方法

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

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

    希望这可以帮助其他面临此问题的人。

    【讨论】:

    • 我遇到了这个问题,浪费了 2 多天的时间来解决这个问题!谢谢
    【解决方案5】:

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

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

    更一般:

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

    【讨论】:

    • 我的问题是如果我实现这个,字体大小也会被覆盖吗?如何避免这种情况?
    • this 非常适合不覆盖字体大小!
    • 有没有办法像这样在不指定大小的情况下全局设置字体?这样,如果我有一个带有字幕样式的表格单元格,文本仍会以我选择的字体以这些样式的默认大小显示?
    • @KrutarthPatel 请参阅下面的解决方案。字体大小未被覆盖。
    猜你喜欢
    • 1970-01-01
    • 2015-05-22
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-28
    • 2012-02-21
    • 1970-01-01
    相关资源
    最近更新 更多