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

我有一个自定义字体,我想用于在我的应用程序,标签,文本视图等显示文本的一切。

有没有一种方法来设置整个应用程序的默认字体(标签默认使用SystemFont)?

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

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

这将设置字体为您的应用程序中所有UILabel的自定义字体。 你需要为每个控件重复它(UIButton,UILabel等)。

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

还有另一个解决scheme,将覆盖systemFont。

只需创build一个类别

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。

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

 extension UILabel { 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 { var substituteFontName : String { get { return self.font.fontName } set { if self.font.fontName.rangeOfString("Medium") == nil { self.font = UIFont(name: newValue, size: self.font.pointSize) } } } var substituteFontNameBold : String { get { return self.font.fontName } set { if self.font.fontName.rangeOfString("Medium") != nil { self.font = UIFont(name: newValue, size: self.font.pointSize) } } } } 

那么对于你的UIA代理人来说:

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

注意:如果您发现粗体replace不起作用,则可能默认字体名称不包含“中”。 根据需要将这个string转换为另一个匹配(感谢下面的评论中的梅森)。

Swift 3.1

基于FábioOliveira的回答( https://stackoverflow.com/a/23042694/2082851 ),我做了我自己的迅速3.1。

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

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

 struct AppFontName { static let regular = "CourierNewPSMT" static let bold = "CourierNewPS-BoldMT" static let italic = "CourierNewPS-ItalicMT" } extension UIFont { class func mySystemFont(ofSize size: CGFloat) -> UIFont { return UIFont(name: AppFontName.regular, size: size)! } class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont { return UIFont(name: AppFontName.bold, size: size)! } class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont { return UIFont(name: AppFontName.italic, size: size)! } convenience init(myCoder aDecoder: NSCoder) { if let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor { if let fontAttribute = fontDescriptor.fontAttributes["NSCTFontUIUsageAttribute"] as? String { 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)! } else { self.init(myCoder: aDecoder) } } else { self.init(myCoder: aDecoder) } } class func overrideInitialize() { if self == UIFont.self { let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))) let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) method_exchangeImplementations(systemFontMethod, mySystemFontMethod) let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))) let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod) let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))) let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod) 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 3.1 // 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() } ... } 

从Hugues BR开发回答,但使用方法swizzling我已经到达一个解决scheme,成功地将所有字体更改为我的应用程序中所需的字体。

dynamictypes的方法应该是您应该在iOS 7上寻找的方法。以下解决scheme不使用dynamictypes。


笔记:

  • 下面的代码,在提交的状态,从未提交给苹果的批准;
  • 有一个更短的版本通过苹果提交,即没有- initWithCoder:覆盖。 但是这并不包括所有的情况;
  • 下面的代码是存在于我用来设置我的AppDelegate类包括我的应用程序的风格,因此到处都可用和所有的UIFont实例;
  • 我在这里使用Zapfino只是为了使变化更加明显。
  • 你可能会发现这个代码的任何改进是值得欢迎的。

该解决scheme使用两种不同的方法来实现最终结果。 第一个是覆盖UIFont类的方法+ systemFontWithSize: systemFontWithSize + systemFontWithSize:和类似的使用我的替代品(在这里我用“Zapfino”毫不怀疑replace是成功的)。

另一种方法是覆盖UIFont上的- initWithCoder:方法,以replace任何出现的CTFontRegularUsage和类似的replace项。 这最后一个方法是必要的,因为我发现在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 

为了完成Sandy Chapman的回答 ,下面是Objective-C中的一个解决scheme(把这个类别放在你想改变UILabel Apperance ):

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

然后,你可以改变Apperance

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

我发表了它作为一个新的回应,而不是作为一个评论,因为我没有足够的声誉。

对SWIFT 3.0和SWIFT警告的注释

您可以按行删除警告消息:

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

通过将其replace为:

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

也许不会,你可能会自己设置字体在你的控制上,但是你可以通过集中你从哪里得到字体types来简化这个过程,比如让应用程序委托或者其他普通的类有一个返回字体和任何需要设置字体的东西都可以调用该方法,这将有助于在需要更改字体的情况下,将字体更改为一个位置,而不是设置字体的任何位置。另一种方法是将子类你的UI元素将自动设置字体,但这可能是矫枉过正的..

这些解决scheme都不能在整个应用程序中普遍使用。 有一件事我发现可以帮助pipe理Xcode中的字体,将Storyboard打开为源代码(在文件导航器中按住Control键单击故事板>“打开为”>“源”),然后执行查找和replace。

字体types总是设置在代码和笔尖/故事板。

对于代码,就像Hugues BR说的那样,在类别中可以解决问题。

对于笔尖/故事板,我们可以使用方法Swizzling awakeFromNib来更改字体types,因为从笔尖/故事板的UI元素始终在屏幕中显示之前调用它。

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

的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 

的UIButton:

 #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改成一个macros。

对于Swift 3

以上所有答案都是正确的,但是我已经按照设备大小以不同的方式做了。 这里,在ATFontManager类中,我已经在类的顶部定义了默认字体大小为defaultFontSizeForIphone7Plus ,这是iphone 7plus和iphone 6 plus的字体大小,您可以根据您的要求进行更改。

  class ATFontManager: UIFont{ class func setFont(iPhone7PlusFontSize: CGFloat? = nil,andFontName fontN : String = FontName.HelveticaNeue.rawValue) -> UIFont{ let defaultFontSizeForIphone7Plus : CGFloat = 16 switch ATDeviceDetector().screenType { case .iPhone4: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize - 3)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus - 6)! case .iPhone5: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize - 2)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus - 3)! case .iPhone6AndIphone7: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize - 1)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus - 1)! case .iPhone6PAndIPhone7P: return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSizeForIphone7Plus)! case .ipadmini: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize + 2)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus + 1)! case .ipadpro: if let fontSize = iPhone7PlusFontSize{ return UIFont(name: fontN, size: fontSize + 3)! } return UIFont(name: fontN, size: defaultFontSizeForIphone7Plus + 2)! default: return UIFont(name: fontN, size: iPhone7PlusFontSize ?? 15)! } } } 

我添加了某种字体名称,为了更多,您可以在这里添加字体名称和types。

  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 } enum ScreenType: String { case iPhone4 case iPhone5 case iPhone6AndIphone7 case iPhone6PAndIPhone7P case ipadmini case ipadpro 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 1024.0: return .ipadmini case 1366.0: return .ipadpro 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) 

NUI是UIAppearance代理的替代品。 通过简单地修改样式表,它可以控制整个应用程序中大量UI元素types的字体(以及其他许多属性),可以在多个应用程序中重用。

NUILabel类添加到标签后,您可以在样式表中轻松控制其字体:

 LabelFontName String Helvetica 

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

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

File – New – 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) } } 

创build子视图控制器并与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() } } 

注意:父VC中声明的字体和颜色在CustomFontLabel中实现。 优点是我们可以通过Parent VC的一些简单的改变,一起改变uilabel /任何视图的属性。

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) } } }