在故事板中使用自定义字体?

70

我在我的iOS项目中添加了字体。它在项目中,并在构建项目时复制。它似乎是一个有效的字体,如果通过应用程序列出设备上的所有字体,它将显示出来。我正确地设置了plist以包含该字体。但我无法让它在Xcode 4.2的故事板部分中显示,以便在文本控件、按钮等中使用它。此外,它似乎不允许我输入字体名称,而是强制我使用字体对话框。我还尝试在系统中安装此字体,但无法让它显示在这个列表中。我需要仅在代码中完成这个操作,或者可以通过故事板界面完成吗?

请注意,我可以在代码中使其正常工作,但通过故事板完成将更加方便。


找到了一个可能更少痛苦的“全面转换”工具,但在IB或storyboards方面还没有消息。它的工作方式大致如下:[[UITextView appearance] setFont:[UIFont fontWithName:@"字体名称" size:18]]; - slycrel
一年过去了,仍然没有任何消息。希望在 WWDC 时间左右能够解决这个问题! - slycrel
7个回答

147

更新:Xcode 6的Interface Builder现在允许您选择自定义字体,并在设计时正确呈现。

我知道这个问题很老,但我一直在努力寻找一种在iOS 5中轻松指定Storyboard(或Interface Builder)自定义字体的方法,我找到了一个相当方便的解决方案。

首先,请确保按照此教程将字体添加到项目中。还要记住,可以使用UIAppearance代理setTitleTextAttributes:方法来指定UINavigationBar、UITabBar和UISegmentedControl的自定义字体。

为UIButton、UITextField、UILabel和任何其他需要自定义字体的组件添加以下类别。这些类别只是实现了一个新属性fontName,它会改变元素的当前字体,同时保持字体大小不变。

要在Storyboard中指定字体,只需选择所需的元素(标签、按钮、文本视图等),并添加一个用户定义的运行时属性,其中键路径设置为字符串类型的fontName,值为您自定义字体的名称。

Custom font Storyboard

就这样,您甚至不需要导入类别。这样,您就不需要为每个需要自定义字体的UI组件创建出口,并且不需要手动编码。

请注意,在Storyboard中字体不会显示,但在设备或模拟器上运行时将会看到它。


类别文件

UIButton+TCCustomFont.h:

#import <UIKit/UIKit.h>

@interface UIButton (TCCustomFont)
@property (nonatomic, copy) NSString* fontName;
@end

UIButton+TCCustomFont.m:

#import "UIButton+TCCustomFont.h"

@implementation UIButton (TCCustomFont)

- (NSString *)fontName {
    return self.titleLabel.font.fontName;
}

- (void)setFontName:(NSString *)fontName {
    self.titleLabel.font = [UIFont fontWithName:fontName size:self.titleLabel.font.pointSize];
}

@end

UILabel+TCCustomFont.h:

#import <UIKit/UIKit.h>

@interface UILabel (TCCustomFont)
@property (nonatomic, copy) NSString* fontName;
@end

UILabel+TCCustomFont.m:

#import "UILabel+TCCustomFont.h"

@implementation UILabel (TCCustomFont)

- (NSString *)fontName {
    return self.font.fontName;
}

- (void)setFontName:(NSString *)fontName {
    self.font = [UIFont fontWithName:fontName size:self.font.pointSize];
}

@end

UITextField+TCCustomFont.h:

#import <UIKit/UIKit.h>

@interface UITextField (TCCustomFont)
@property (nonatomic, copy) NSString* fontName;
@end

UITextField+TCCustomFont.m:

#import "UITextField+TCCustomFont.h"

@implementation UITextField (TCCustomFont)

- (NSString *)fontName {
    return self.font.fontName;
}

- (void)setFontName:(NSString *)fontName {
    self.font = [UIFont fontWithName:fontName size:self.font.pointSize];
}

@end

也可从GIST下载,链接如下:单个文件多个文件

故障排除

如果您运行时遇到fontName属性未指定的运行时错误,请在项目设置中添加标志-all_load其他链接器标志下,以强制链接器包含类别。


3
这是一个很好的答案,几乎就是我需要的。但是,如果你正在为iOS 6(在我的情况下是Xcode 4.6.3)进行开发,则需要再进行一步才能显示自定义字体。 在导航器中选择您的项目,然后转到TARGETS -> Build Phases,然后在Copy Bundle Resources面板底部点击“+”按钮。选择您的自定义字体文件,它应该出现在列表中。 - Chris Kobrzak
2
有一件事需要注意,因为我经常会错过它:一旦创建了新的用户定义运行时属性,并输入了关键路径的名称,如果您在选择字符串类型之前没有按回车键,则刚刚输入的关键路径将被重置。 我一直想知道为什么会出现关键路径错误,原来是这个原因。 - Eric
1
我尝试使用“用户定义的运行时属性”,但是出现了以下错误:“UILabel这个类不符合键值编码的键fontName。”你有什么想法我错过了什么吗? - Thomas Besnehard
1
@Tommecpe,您错过了最后一步,在故障排除部分。 - redent84
1
我按照Storyboard中自定义字体的所有步骤进行了操作,并且使用的是Xcode 5.1...但是我遇到了运行时错误。 - user1169079
显示剩余7条评论

62
自 Xcode6.0 起,根据 Xcode6.0 发布说明,Interface Builder 可以在设计时呈现嵌入式自定义 iOS 字体,更准确地预览完成的应用程序外观和正确的尺寸。您可以按以下方式设置 storyboard 中的标签字体:
  1. 获取您的自定义字体文件(.ttf、.ttc)
  2. 将字体文件导入 Xcode 项目中
  3. 在 app-info.plist 中添加一个名为“Fonts provided by application”的键。它是一个数组类型,将所有字体文件名添加到数组中,注意要包括文件扩展名。
  4. enter image description here

  5. 在 storyboard 中,将 UILabel 拖动到您的界面上,选择标签,并导航到“Attribute Inspector”,单击“Font”选择区域的右侧图标按钮。在弹出面板中,选择“Font”为“Custom”,并选择您嵌入字体名称的“Family”。
  6. enter image description here

参考资料:
  • Xcode 6.0 发布说明
  • WWDC 2014:Interface Builder 的新功能
  • IOS-Keys:UIAppFonts:关于应用程序字体设置的相关信息。

  • TCCustomFont在我的Xcode 6中无法正常工作。因此,我使用了这种方法,现在它可以正常工作了。 - skycrew
    值得注意的是,这种方法在UILabel上运行得非常完美,但在UITextFields上却不起作用。我仍在努力解决它...我猜实时属性会修复它。 - Nour Helmi
    15
    仅适用于使用普通UILabel而非带属性文本的情况下。 - pojo

    5

    这是XCode中的一个错误,从3.x版本开始就存在,但至今仍未修复。我也遇到了同样的问题,甚至尝试将其添加到我的系统中,但没有成功。这里有另一个关于此问题的SO帖子(链接)


    我已经搜索了一些内容,似乎无法找到这是否是苹果公司已知的问题... 您知道这方面的信息来源吗? - slycrel

    3

    Monjer的回答是正确的。如果您和我一样在编译后看不到添加的字体,请确保将字体添加到构建阶段(目标->构建阶段->复制捆绑资源->添加您的字体文件)。


    1
    截至XCode 9.4,XCode仍然不直接在故事板中使用字体。您可以在设计时看到它们,但在运行时无法看到。如果您正在使用fontWithName API,则会发现它返回nil,但是在storyboard / xib中使用时,无法知道为什么它不出现。
    唯一确保它在运行时从Storyboard / XIB中立即工作的方法是将.ttc / .ttf添加到“Copy Bundle Resources”构建阶段中。
    截至9.4,将字体文件名添加到info.plist似乎不再是必需的。

    0

    这些方法都没对我起作用,但这个方法可以。

    #import <UIKit/UIKit.h>
    
    @interface UILabelEx : UILabel
    
    
    @end
    
    #import "UILabelEx.h"
    #import "Constants.h"
    
    @implementation UILabelEx
    
    - (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {
        [super traitCollectionDidChange: previousTraitCollection];
    
        self.font = [UIFont fontWithName:APP_FONT size:self.font.pointSize];   
    }
    @end
    

    0

    redent84的解决方案非常棒!

    我只想添加一个改进,将类别添加到NSObject上,这样您只需要执行一次即可。

    NSObject+CustomFont.h

    #import <Foundation/Foundation.h>
    
    @interface NSObject (CustomFont)
    
    @property (strong, nonatomic) NSString *fontName;
    @property (strong, nonatomic) UIFont *font;
    
    @end
    

    NSObject+CustomFont.m

    #import "NSObject+CustomFont.h"
    
    @implementation NSObject (CustomFont)
    
    @dynamic font;
    
    - (NSString *)fontName
    {
        return self.font.fontName;
    }
    
    - (void)setFontName:(NSString *)fontName
    {
        self.font = [UIFont fontWithName:fontName size:self.font.pointSize];
    }
    
    @end
    

    1
    好主意。不幸的是,自从iOS 3.0以来,UIButton类的“font”属性已被弃用,因此不建议在UIButtons中使用。 - redent84

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接