为整个 iOS 应用程序设置默认字体?

Posted

技术标签:

【中文标题】为整个 iOS 应用程序设置默认字体?【英文标题】:Set a default font for whole iOS app? 【发布时间】:2012-02-01 04:28:46 【问题描述】:

我有一个自定义字体,我想将其用于在我的应用程序、标签、文本视图等中显示文本的所有内容。

有没有办法为整个应用设置默认字体(标签默认使用 SystemFont)?

【问题讨论】:

对这种困境进行了大量调查。老实说,我们发现最简单的方法就是为每个控件创建一个(微不足道的)新类。所以对于 UIButton,制作 SJButton。不要忘记同时覆盖 initWithFrame 和 initWithCode。为每个控件(比如 UIButton 等)设置颜色或任何你喜欢的颜色。仔细选择 int 代码中的大小(即,这将是在故事板上设置的大小),然后(根据您的喜好)使用该大小(并设置,比如说,字体,颜色 - 随便什么)。它只有几行代码,非常整洁,从长远来看可以为您节省大量时间。 @JoeBlow 感谢您发布您的发现 - 正要花时间寻找自己的答案 @jj- 对。不要忘记,这些天你肯定必须使用IBDesignable。希望能帮助到你。还可以考虑这个有趣的 QA:***.com/a/38000466/294884 【参考方案1】:

ios 5 中使用 UIAppearance 代理似乎是可能的。

 [[UILabel appearance] setFont:[UIFont fontWithName:@"YourFontName" size:17.0]];

这会将字体设置为您应用中所有 UILabel 的自定义字体。您需要为每个控件(UIButton、UILabel 等)重复此操作。

请记住,您需要将 UIAppFonts 值放在 info.plist 中,并包含您要包含的字体的名称。

【讨论】:

感谢您的回复。我能够让它工作。你知道有没有办法在不指定字体大小的情况下指定字体?我的应用中有不同字体大小的标签。 我可以在不覆盖每个实例的磅值的情况下这样做吗? setFont: 方法已弃用 @Anand 你确定吗?我没有看到它在UILabel 中被标记为已弃用。 UIButton 已弃用它,但它使用titleLabel 属性的字体而不是UILabel,因此只需使用UILabel 的外观代理设置字体就可以了。 @Anand 它不被 UILabel 弃用。【参考方案2】:

斯威夫特 5

根据 Fábio Oliveira 的回答 (https://***.com/a/23042694/2082851),我自己制作了 swift 4。

简而言之,这个扩展用我的自定义方法交换默认函数init(coder:)systemFont(ofSize:)boldSystemFont(ofSize:)italicSystemFont(ofSize:)

请注意,它没有完全实现,但您可以根据我的实现交换更多方法。

import UIKit

struct AppFontName 
    static let regular = "CourierNewPSMT"
    static let bold = "CourierNewPS-BoldMT"
    static let italic = "CourierNewPS-ItalicMT"


extension UIFontDescriptor.AttributeName 
    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")


extension UIFont 
    static var isOverrided: Bool = false

    @objc class func mySystemFont(ofSize size: CGFloat) -> UIFont 
        return UIFont(name: AppFontName.regular, size: size)!
    

    @objc class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont 
        return UIFont(name: AppFontName.bold, size: size)!
    

    @objc class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont 
        return UIFont(name: AppFontName.italic, size: size)!
    

    @objc convenience init(myCoder aDecoder: NSCoder) 
        guard
            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else 
                self.init(myCoder: aDecoder)
                return
        
        var fontName = ""
        switch fontAttribute 
        case "CTFontRegularUsage":
            fontName = AppFontName.regular
        case "CTFontEmphasizedUsage", "CTFontBoldUsage":
            fontName = AppFontName.bold
        case "CTFontObliqueUsage":
            fontName = AppFontName.italic
        default:
            fontName = AppFontName.regular
        
        self.init(name: fontName, size: fontDescriptor.pointSize)!
    

    class func overrideInitialize() 
        guard self == UIFont.self, !isOverrided else  return 

        // Avoid method swizzling run twice and revert to original initialize function
        isOverrided = true

        if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) 
            method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
        

        if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
            let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) 
            method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
        

        if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
            let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) 
            method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
        

        if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))), // Trick to get over the lack of UIFont.init(coder:))
            let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) 
            method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
        
    



class AppDelegate: UIResponder, UIApplicationDelegate 
    // Avoid warning of Swift
    // Method 'initialize()' defines Objective-C class method 'initialize', which is not guaranteed to be invoked by Swift and will be disallowed in future versions
    override init() 
        super.init()
        UIFont.overrideInitialize()
    
    ...

【讨论】:

最佳答案!!自动覆盖系统字体,绚丽 如果有人对“NSCTFontUIUsageAttribute”行有疑问:if let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String 为我解决了问题。 似乎不适用于设置文本样式(粗体、标题、标题等)的UILabels...仅适用于具有特定大小和系统字体集的字体。 @nahung89 这也会切换一些系统 UI 字体。例如,键盘建议列表和操作表。不知道这是否会导致苹果拒绝该应用 自发布此答案以来已经一年了。有没有人有更“原生”的 Apple 方式来实现这一目标?【参考方案3】:

还有另一个解决方案是覆盖 systemFont。

只需创建一个类别

UIFont+SystemFontOverride.h

#import <UIKit/UIKit.h>

@interface UIFont (SystemFontOverride)
@end

UIFont+SystemFontOverride.m

@implementation UIFont (SystemFontOverride)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"

+ (UIFont *)boldSystemFontOfSize:(CGFloat)fontSize 
    return [UIFont fontWithName:@"fontName" size:fontSize];


+ (UIFont *)systemFontOfSize:(CGFloat)fontSize 
    return [UIFont fontWithName:@"fontName" size:fontSize];


#pragma clang diagnostic pop

@end

这将替换默认实现,并且大多数 UIControls 使用 systemFont。

【讨论】:

这符合苹果指南吗? 这更像是一种黑客行为。我没有使用这个 hack 添加我的应用程序注册,因为它没有使用任何私有方法。如果你想要一个更强大的解决方案,我也建议你检查一下:github.com/0xced/FontReplacer 这很好。 Apple 只是不希望您使用未记录的功能。您可以“混搭”公开的方法。 当一个类别的方法与它所扩展的类具有相同的签名时,行为是未定义的。要替换类方法,您应该使用方法调配(这也不是一个好主意)。 正如其他人指出的那样,这种解决方案虽然在大多数情况下可能有效,但在技术上会引入未定义行为的可能性。如果您不想冒险,那么方法调配可能是一个更好的选择。这里的答案通过 swizzling 提供了相同的解决方案:***.com/questions/19542942/…【参考方案4】:

如果你使用 Swift,你可以创建一个 UILabel 扩展:

extension UILabel 

    @objc var substituteFontName : String 
        get  return self.font.fontName 
        set  self.font = UIFont(name: newValue, size: self.font.pointSize) 
    


然后你在哪里进行外观代理:

UILabel.appearance().substituteFontName = applicationFont

在名称为 substituteFontName 的属性上使用 UI_APPEARANCE_SELECTOR 的等效 Objective-C 代码。

加法

如果您想分别设置粗体和常规字体:

extension UILabel 

    @objc var substituteFontName : String 
        get  return self.font.fontName 
        set  
            if self.font.fontName.range(of:"Medium") == nil  
                self.font = UIFont(name: newValue, size: self.font.pointSize)
            
        
    

    @objc var substituteFontNameBold : String 
        get  return self.font.fontName 
        set  
            if self.font.fontName.range(of:"Medium") != nil  
                self.font = UIFont(name: newValue, size: self.font.pointSize)
            
        
    

然后为您的 UIAppearance 代理:

UILabel.appearance().substituteFontName = applicationFont
UILabel.appearance().substituteFontNameBold = applicationFontBold

注意:如果您发现粗体替换不起作用,则默认字体名称可能不包含“中”。根据需要切换该字符串以进行另一场比赛(感谢下面 cmets 中的 Mason)。

【讨论】:

我发现的一个缺点是,当我使用 UIAlertController 启动警报时,具有 .Cancel 样式的按钮与具有 .Default 样式的按钮相同(至少在使用 GillSans 时) )。而通常 .Cancel 将是常规粗细字体,而 .Default 将是粗体。有什么想法吗? 对不起,我的意思是 .Cancel 标签通常是粗体,而 Default 通常是常规重量。 @MasonG.Zhwiti 在这种情况下,我可能会设置UILabel 扩展来为粗体添加一个额外的字体名称。然后在set 中检查字体名称中是否有“粗体”,并在一种情况下忽略该设置,并在另一种情况下使用它。我将编辑并添加一个示例。 @SandyChapman 谢谢!我正在尝试这种新技术,这很有意义,但它似乎对我不起作用。我在 iOS 8.3 模拟器上使用 GillSans 和 GillSans-Bold。你测试过这种技术吗? @SandyChapman 我知道发生了什么。 iOS 8 的默认字体往往是 HelveticaNeueInterface-Regular 或(粗体)HelveticaNeueInterface-MediumP4。因此,寻找“Bold”永远不会匹配任何东西。我将其更改为 rangeOfString("Medium") 并且有效。【参考方案5】:

从 Hugues BR 的答案中开发,但使用调配方法,我已经找到了一个解决方案,可以成功地将我的应用程序中的所有字体更改为所需的字体。

动态类型的方法应该是您应该在 iOS 7 上寻找的方法。以下解决方案不使用动态类型。


注意事项:

以下代码在其呈现状态下从未提交给 Apple 批准; 有一个较短的版本通过了 Apple 提交,即没有 - initWithCoder: 覆盖。但是,这并不能涵盖所有情况; 以下代码存在于我用来设置我的应用程序样式的类中,该类包含在我的 AppDelegate 类中,因此可用于任何地方和所有 UIFont 实例; 我在这里使用 Zapfino 只是为了使更改更加明显; 欢迎您对此代码进行任何改进。

此解决方案使用两种不同的方法来实现最终结果。第一个是覆盖 UIFont 类方法 + systemFontWithSize: 并且与使用我的替代方法的方法类似(这里我使用“Zapfino”来确保替换成功)。

另一种方法是覆盖 UIFont 上的 - initWithCoder: 方法,以用我的替代方法替换任何出现的 CTFontRegularUsage 和类似的。 最后一种方法是必要的,因为我发现在 NIB 文件中编码的 UILabel 对象不会检查 + systemFontWithSize: 方法来获取它们的系统字体,而是将它们编码为 UICTFontDescriptor 对象。 我试图覆盖- awakeAfterUsingCoder:,但不知何故,它被我的故事板中的每个编码对象调用并导致崩溃。覆盖- awakeFromNib 不允许我读取NSCoder 对象。

#import <objc/runtime.h>

NSString *const FORegularFontName = @"Zapfino";
NSString *const FOBoldFontName = @"Zapfino";
NSString *const FOItalicFontName = @"Zapfino";

#pragma mark - UIFont category
@implementation UIFont (CustomFonts)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+ (void)replaceClassSelector:(SEL)originalSelector withSelector:(SEL)modifiedSelector 
    Method originalMethod = class_getClassMethod(self, originalSelector);
    Method modifiedMethod = class_getClassMethod(self, modifiedSelector);
    method_exchangeImplementations(originalMethod, modifiedMethod);


+ (void)replaceInstanceSelector:(SEL)originalSelector withSelector:(SEL)modifiedSelector 
    Method originalDecoderMethod = class_getInstanceMethod(self, originalSelector);
    Method modifiedDecoderMethod = class_getInstanceMethod(self, modifiedSelector);
    method_exchangeImplementations(originalDecoderMethod, modifiedDecoderMethod);


+ (UIFont *)regularFontWithSize:(CGFloat)size

    return [UIFont fontWithName:FORegularFontName size:size];


+ (UIFont *)boldFontWithSize:(CGFloat)size

    return [UIFont fontWithName:FOBoldFontName size:size];


+ (UIFont *)italicFontOfSize:(CGFloat)fontSize

    return [UIFont fontWithName:FOItalicFontName size:fontSize];


- (id)initCustomWithCoder:(NSCoder *)aDecoder 
    BOOL result = [aDecoder containsValueForKey:@"UIFontDescriptor"];

    if (result) 
        UIFontDescriptor *descriptor = [aDecoder decodeObjectForKey:@"UIFontDescriptor"];

        NSString *fontName;
        if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontRegularUsage"]) 
            fontName = FORegularFontName;
        
        else if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontEmphasizedUsage"]) 
            fontName = FOBoldFontName;
        
        else if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontObliqueUsage"]) 
            fontName = FOItalicFontName;
        
        else 
            fontName = descriptor.fontAttributes[@"NSFontNameAttribute"];
        

        return [UIFont fontWithName:fontName size:descriptor.pointSize];
    

    self = [self initCustomWithCoder:aDecoder];

    return self;


+ (void)load

    [self replaceClassSelector:@selector(systemFontOfSize:) withSelector:@selector(regularFontWithSize:)];
    [self replaceClassSelector:@selector(boldSystemFontOfSize:) withSelector:@selector(boldFontWithSize:)];
    [self replaceClassSelector:@selector(italicSystemFontOfSize:) withSelector:@selector(italicFontOfSize:)];

    [self replaceInstanceSelector:@selector(initWithCoder:) withSelector:@selector(initCustomWithCoder:)];

#pragma clang diagnostic pop

@end

【讨论】:

你如何在没有 UIFontDescriptor 的 iOS6 上使用这个实现 我使用解码器键“UIFontTraits”来检查提供的字体是粗体还是斜体,并用我自己的变体替换它。从这里的要点得到它gist.github.com/Daij-Djan/5046612。 感谢您的回答,我现在使用了另一种解决方案。当我再次需要它时,我会检查它:) 感谢@FábioOliveira,它就像一个魅力!您还需要将 #import 放在标题上,否则使用“方法”类会出错(我在 XCode 6 中遇到的错误) 出于某种原因,在 iOS 8 上,modals (UIAlertController) 不会改变字体。【参考方案6】:

要完成Sandy Chapman's answer,这里有一个Objective-C 中的解决方案(把这个类别放在任何你想改变的地方UILabelAppearance):

@implementation UILabel (FontOverride)
- (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR 
    self.font = [UIFont fontWithName:name size:self.font.pointSize];

@end

接口文件,应该公开声明这个方法,以便以后在你的应用委托等地方使用:

@interface UILabel (FontOverride)
  - (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR;
@end

然后,您可以将Appearance 更改为:

[[UILabel appearance] setSubstituteFontName:@"SourceSansPro-Light"];

【讨论】:

您好,您的意思是“任何地方”,必须在每个视图控制器中添加该代码,并且在您希望更改字体的控制器中使用每个 UILabel? 不,你必须把这段代码一次放在你项目的任何地方;例如在您的 appdelegate 中。 @DamienDebin 我想将粗体字体用于粗体,但这会将粗体变为浅色。有办法吗? 其实可以,但是应该是“Category”还是“Extension”呢?这里解释的区别:***.com/questions/7136124/…【参考方案7】:

在查看了几篇帖子后,我为 Swift 4 创建了自己的字体转换,它涵盖了大多数情况,例如:

1st 将字体添加到项目结构和 .plist 文件(同名):

<key>UIAppFonts</key>
<array>
    <string>Typo-Light.ttf</string>
    <string>Typo-Regular.ttf</string>
    <string>Typo-Semibold.ttf</string>
    <string>Typo-LightItalic.ttf</string>
</array>

然后

struct Resources 

    struct Fonts 
        //struct is extended in Fonts
    


extension Resources.Fonts 

    enum Weight: String 
        case light = "Typo-Light"
        case regular = "Typo-Regular"
        case semibold = "Typo-Semibold"
        case italic = "Typo-LightItalic"
    


extension UIFontDescriptor.AttributeName 
    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")


extension UIFont 

    @objc class func mySystemFont(ofSize: CGFloat, weight: UIFont.Weight) -> UIFont 
        switch weight 
        case .semibold, .bold, .heavy, .black:
            return UIFont(name: Resources.Fonts.Weight.semibold.rawValue, size: ofSize)!

        case .medium, .regular:
            return UIFont(name: Resources.Fonts.Weight.regular.rawValue, size: ofSize)!

        default:
            return UIFont(name: Resources.Fonts.Weight.light.rawValue, size: ofSize)!
        
    

    @objc class func mySystemFont(ofSize size: CGFloat) -> UIFont 
        return UIFont(name: Resources.Fonts.Weight.light.rawValue, size: size)!
    

    @objc class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont 
        return UIFont(name: Resources.Fonts.Weight.semibold.rawValue, size: size)!
    

    @objc class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont 
        return UIFont(name: Resources.Fonts.Weight.italic.rawValue, size: size)!
    

    @objc convenience init(myCoder aDecoder: NSCoder) 
        guard
            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else 
                self.init(myCoder: aDecoder)
                return
        
        var fontName = ""
        switch fontAttribute 
        case "CTFontRegularUsage", "CTFontMediumUsage":
            fontName = Resources.Fonts.Weight.regular.rawValue
        case "CTFontEmphasizedUsage", "CTFontBoldUsage", "CTFontSemiboldUsage","CTFontHeavyUsage", "CTFontBlackUsage":
            fontName = Resources.Fonts.Weight.semibold.rawValue
        case "CTFontObliqueUsage":
            fontName = Resources.Fonts.Weight.italic.rawValue
        default:
            fontName = Resources.Fonts.Weight.light.rawValue
        
        self.init(name: fontName, size: fontDescriptor.pointSize)!
    

    class func overrideDefaultTypography() 
        guard self == UIFont.self else  return 

        if let systemFontMethodWithWeight = class_getClassMethod(self, #selector(systemFont(ofSize: weight:))),
            let mySystemFontMethodWithWeight = class_getClassMethod(self, #selector(mySystemFont(ofSize: weight:))) 
            method_exchangeImplementations(systemFontMethodWithWeight, mySystemFontMethodWithWeight)
        

        if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) 
            method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
        

        if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
            let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) 
            method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
        

        if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
            let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) 
            method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
        

        if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))),
            let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) 
            method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
        
    

最后在Appdelegate 调用创建的方法,如下:

class AppDelegate: UIResponder, UIApplicationDelegate 
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool 

        UIFont.overrideDefaultTypography()
        return true
    

【讨论】:

@sheshnath 你能给我们更多的崩溃信息吗? 对不起,错误是我这边的,info.plist中没有列出字体 @midhunp 你能更明确一点,这样它对你不起作用吗?粗体字很适合我。【参考方案8】:

对 SWIFT 3.0 和 SWIFT 警告的评论

您可以删除行中的警告消息:

let initCoderMethod = class_getInstanceMethod(self, Selector("initWithCoder:"))

将其替换为:

let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:)))

【讨论】:

大声笑。我不知道 Swift 允许使用它。顺便说一句,我会将其更新为上述答案。谢谢@ucotta!【参考方案9】:

对于 Swift 5

以上所有答案都是正确的,但我以根据设备尺寸的方式做了一些不同的事情。 在这里,在 ATFontManager 类中,我将默认字体大小设置为在类的顶部定义为 defaultFontSize,这是字体大小 iphone plus,你可以根据你的要求进行更改。

class ATFontManager: UIFont
    
    class func setFont( _ iPhone7PlusFontSize: CGFloat? = nil,andFontName fontN : String = FontName.helveticaNeue) -> UIFont
        
        let defaultFontSize : CGFloat = 16
        
        switch ATDeviceDetector().screenType 
            
        case .iPhone4:
            if let fontSize = iPhone7PlusFontSize
                return UIFont(name: fontN, size: fontSize - 5)!
            
            return UIFont(name: fontN, size: defaultFontSize - 5)!
            
        case .iPhone5:
            if let fontSize = iPhone7PlusFontSize
                return UIFont(name: fontN, size: fontSize - 3)!
            
            return UIFont(name: fontN, size: defaultFontSize - 3)!
            
        case .iPhone6AndIphone7, .iPhoneUnknownSmallSize:
            if let fontSize = iPhone7PlusFontSize
                return UIFont(name: fontN, size: fontSize - 2)!
            
            return UIFont(name: fontN, size: defaultFontSize - 2)!
            
        case .iPhone6PAndIPhone7P, .iPhoneUnknownBigSize:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSize)!
        case .iPhoneX, .iPhoneXsMax:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSize)!
          
        case .iPadMini:
            if let fontSize = iPhone7PlusFontSize
                return UIFont(name: fontN, size: fontSize + 2)!
            
            return UIFont(name: fontN, size: defaultFontSize + 2)!
            
        case .iPadPro10Inch:
            if let fontSize = iPhone7PlusFontSize
                return UIFont(name: fontN, size: fontSize + 4)!
            
            return UIFont(name: fontN, size: defaultFontSize + 4)!
            
        case .iPadPro:
            if let fontSize = iPhone7PlusFontSize
                return UIFont(name: fontN, size: fontSize + 6)!
            
            return UIFont(name: fontN, size: defaultFontSize + 6)!
            
        case .iPadUnknownSmallSize:
            
            return UIFont(name: fontN, size: defaultFontSize + 2)!
            
        case .iPadUnknownBigSize:
            
            return UIFont(name: fontN, size: defaultFontSize + 4)!
            
        default:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? 16)!
        
    

     

我已经添加了某些字体名称,更多您可以添加字体名称并在此处输入。

   enum FontName : String 
        case HelveticaNeue = "HelveticaNeue"
        case HelveticaNeueUltraLight = "HelveticaNeue-UltraLight"
        case HelveticaNeueBold = "HelveticaNeue-Bold"
        case HelveticaNeueBoldItalic = "HelveticaNeue-BoldItalic"
        case HelveticaNeueMedium = "HelveticaNeue-Medium"
        case AvenirBlack = "Avenir-Black"
        case ArialBoldMT = "Arial-BoldMT"
        case HoeflerTextBlack = "HoeflerText-Black"
        case AMCAPEternal = "AMCAPEternal"
    

该类引用设备检测器,以便根据设备提供适当的字体大小。

class ATDeviceDetector 
    
    var iPhone: Bool 
        
        return UIDevice().userInterfaceIdiom == .phone
    
    
    var ipad : Bool
        
        return UIDevice().userInterfaceIdiom == .pad
    
    
    let isRetina = UIScreen.main.scale >= 2.0
    
    
    enum ScreenType: String 
        
        case iPhone4
        case iPhone5
        case iPhone6AndIphone7
        case iPhone6PAndIPhone7P
        case iPhoneX
        
        case iPadMini
        case iPadPro
        case iPadPro10Inch
        
        case iPhoneOrIPadSmallSizeUnknown
        case iPadUnknown
        case unknown
    
    
    
    struct ScreenSize
        
        static let SCREEN_WIDTH         = UIScreen.main.bounds.size.width
        static let SCREEN_HEIGHT        = UIScreen.main.bounds.size.height
        static let SCREEN_MAX_LENGTH    = max(ScreenSize.SCREEN_WIDTH,ScreenSize.SCREEN_HEIGHT)
        static let SCREEN_MIN_LENGTH    = min(ScreenSize.SCREEN_WIDTH,ScreenSize.SCREEN_HEIGHT)
    
    
    
    var screenType: ScreenType 
        
        switch ScreenSize.SCREEN_MAX_LENGTH 
            
        case 0..<568.0:
            return .iPhone4
        case 568.0:
            return .iPhone5
        case 667.0:
            return .iPhone6AndIphone7
        case 736.0:
            return .iPhone6PAndIPhone7P
        case 812.0:
            return .iPhoneX
        case 568.0..<812.0:
            return .iPhoneOrIPadSmallSizeUnknown
        case 1112.0:
            return .iPadPro10Inch
        case 1024.0:
            return .iPadMini
        case 1366.0:
            return .iPadPro
        case 812.0..<1366.0:
            return .iPadUnknown
        default:
            return .unknown
        
    

如何使用。希望对你有所帮助。

//for default 
label.font = ATFontManager.setFont()

//if you want to provide as your demand. Here **iPhone7PlusFontSize** variable is denoted as font size for *iphone 7plus and iphone 6 plus*, and it **ATFontManager** class automatically handle.
label.font = ATFontManager.setFont(iPhone7PlusFontSize: 15, andFontName: FontName.HelveticaNeue.rawValue)

【讨论】:

【参考方案10】:

这些解决方案都不能在整个应用中通用。我发现有助于在 Xcode 中管理字体的一件事是将情节提要作为源代码打开(在文件导航器中按住 Control 单击情节提要>“打开为”>“源”),然后执行查找和替换。

【讨论】:

【参考方案11】:

字体类型始终在代码和 nib/storyboard 中设置。

对于代码,就像Hugues BR said一样,在分类中做可以解决问题。

对于 nib/storyboard,我们可以通过方法 Swizzling awakeFromNib 来更改字体类型,因为 nib/storyboard 中的 UI 元素总是在屏幕上显示之前调用它。

我想你知道Aspects。它是一个基于 Method Swizzling 的 AOP 编程库。 我们为UILabel、UIButton、UITextView创建分类来实现它。

UILabel:

#import "UILabel+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UILabel (OverrideBaseFont)

+ (void)load 
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) 
        UILabel* instance = [aspectInfo instance];
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize];
        instance.font = font;
    error:nil];


@end

用户界面按钮:

#import "UIButton+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UIButton (OverrideBaseFont)

+ (void)load 
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) 
        UIButton* instance = [aspectInfo instance];
        UILabel* label = instance.titleLabel;
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:label.font.pointSize];
        instance.titleLabel.font = font;
    error:nil];


@end

UITextField:

#import "UITextField+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UITextField (OverrideBaseFont)

+ (void)load 
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) 
        UITextField* instance = [aspectInfo instance];
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize];
        instance.font = font;
    error:nil];


@end

UITextView:

#import "UITextView+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UITextView (OverrideBaseFont)

+ (void)load 
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) 
        UITextView* instance = [aspectInfo instance];
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize];
        instance.font = font;
    error:nil];


@end

就是这样,您可以将 HelveticaNeue-light 更改为带有您的字体名称的宏。

【讨论】:

【参考方案12】:

可能不会,您可能会自己在控件上设置字体,但您可以通过集中获取字体类型的位置来简化流程,例如让应用程序委托或其他一些公共类有一个方法返回字体,任何需要设置字体的东西都可以调用该方法,这将在您需要更改字体时有所帮助,您可以在一个地方而不是在您设置字体的任何地方进行更改...另一种选择可以是制作 UI 元素的子类,它们会自动设置字体,但这可能是矫枉过正..

【讨论】:

作为记录,这就是我所做的,但@Randall 需要代表,并提供了一个很好的答案。我只需要支持不到5.0 我不同意你的做法。当您的问题被标记为 iphone-sdk-4.0 时,您选择的答案无效。 @Sam Jarman,Randall 在下面的回答是正确的 - 你可以为未来的访客标记它吗?【参考方案13】:

对于 AppDelegate 的 FinishedLaunching() 中的 Xamarin.iOS,将代码如下:-

UILabel.Appearance.Font= UIFont.FromName("Lato-Regular", 14);

为整个应用程序设置字体并在 Info.plist 上添加“UIAppFonts”键,路径应该是字体文件 .ttf 所在的路径。对我来说,它位于我项目的“字体”文件夹中。

<key>UIAppFonts</key>
    <array>
        <string>fonts/Lato-Regular.ttf</string>
    </array>

【讨论】:

这行得通,但没有用 - 因为现在你的应用程序中的所有文本都是相同的 14 大小......可能没有办法覆盖它以使其具有原始元素字体大小【参考方案14】:

正如@Randall 在他的answer 中提到的iOS 5.0+ UIAppearance 代理可用于自定义类read more 的所有实例的外观。

UILabel.appearance().font = .systemFont(ofSize: 17, weight: .regular)

【讨论】:

【参考方案15】:

NUI 是 UIAppearance 代理的替代方案。它使您可以通过简单地修改样式表来控制整个应用程序中大量 UI 元素类型的字体(和许多其他属性),该样式表可以在多个应用程序中重复使用。

在标签中添加NUILabel 类后,您可以轻松地在样式表中控制它们的字体:

LabelFontName    String    Helvetica

如果您有不同字体大小的标签,您可以使用 NUI 的 Label、LargeLabel 和 SmallLabel 类来控制它们的大小,甚至可以快速创建自己的类。

【讨论】:

【参考方案16】:

我在swift中使用这种类型的字体类。使用字体扩展类。

enum FontName: String 

  case regular      = "Roboto-Regular"



//MARK: - Set Font Size
enum FontSize: CGFloat 
    case size = 10


extension UIFont 

    //MARK: - Bold Font
  class var regularFont10: UIFont 
        return UIFont(name: FontName.regular.rawValue, size:FontSize.size.rawValue )!
    

【讨论】:

【参考方案17】:

我们在 Swift -Xcode 7.2 中使用父视图控制器和子视图控制器(继承)实现了相同的目标。

文件 - 新建 - Cocoa Touch 类 - ParentViewController。

    import UIKit
    import Foundation

    class ParentViewController: UIViewController 

        var appUIColor:UIColor = UIColor.redColor()
        var appFont:UIFont = UIFont(name: "Copperplate", size: 20)!

        override func viewDidLoad() 
            super.viewDidLoad()
        
        func addStatusBar()
        
            let view = UIView(frame:
                CGRect(x: 0.0, y: 0.0, width: UIScreen.mainScreen().bounds.size.width, height: 20.0)
            )
            view.backgroundColor = appUIColor
            self.view.addSubview(view)
        
        

制作子视图控制器并与 StoryBoard VC 关联,添加 textLabel。

    import UIKit

    class FontTestController: ParentViewController 
        @IBOutlet var testLabel: UILabel!

        override func viewDidLoad() 
            super.viewDidLoad()
            testLabel.font =  appFont
            testLabel.textColor = appUIColor
        

或者创建一个自定义的 UILabel 类(子分类方法)并将所需的标签关联到它。

import Foundation
import UIKit

class CustomFontLabel: UILabel 
    required init(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)!
        backgroundColor = ParentViewController().appUIColor
        font = ParentViewController().appFont
        textColor = UIColor.blackColor()
    

注意:在 Parent VC 中声明的字体和颜色在 CustomFontLabel 中实现。优点是我们可以在 Parent VC 中进行一些简单的更改,同时更改 uilabel/any view 的属性。

2)'for' 为子视图循环 UIView。它仅适用于特定的 VC。

    override func viewWillLayoutSubviews() 
            for view in self.view.subviews  
                if view.isKindOfClass(UITextField) 
                UITextField.appearance().font =  UIFont(name: "Copperplate", size: 20)
                
                if view.isKindOfClass(UILabel) 
                    UILabel.appearance().font =  UIFont(name: "Copperplate", size: 20)    
                               
                   
        

【讨论】:

以上是关于为整个 iOS 应用程序设置默认字体?的主要内容,如果未能解决你的问题,请参考以下文章

如何用css样式设计整个网站字体

DOMPDF为整个页面设置字体?

设置 Swing 程序的默认字体

Android:想要为整个应用程序而不是运行时设置自定义字体

Android - 如何为整个应用程序设置自定义字体[重复]

iOS 文本字体的默认宽度和高度