将自定义字体添加到iOS应用程序中并找到它们的真实名称

39

我需要添加两个字体到我的应用程序中以供使用。

这是字体图片。当前文件名为:

name.font       = [UIFont fontWithName:@"Helvetica Neue LT Pro-Medium" size:10];
headline.font   = [UIFont fontWithName:@"Helvetica Neue LT Pro-Light" size:8];

在 plist 文件的 Font Available 选项 中输入相同的字体名称。

我也尝试添加文件名,例如

HelveticaNeueLTPro-Lt
HelveticaNeueLTPro-Md

但是似乎什么都不起作用。我该怎么获取字体的精确名称。

enter image description here


你真的想要将字体添加到Xcode吗?难道不是你的iOS应用程序吗? - user529758
尝试一下这个:https://dev59.com/52Yq5IYBdhLWcg3wkRYo - iAppDeveloper
我是说我的应用程序 :) - Muhammad Umar
@NaCl 是的,我知道所有这些步骤。我只是困惑应该将哪些名称放置在 plist 键和 UIFont Named 中。 - Muhammad Umar
看看这个:https://dev59.com/1HRC5IYBdhLWcg3wP-n5 - Nishchith Cp
11个回答

85

使用+[UIFont familyNames]可以列出系统中所有已知的字体系列名称。对于每个系列名称,您可以使用+[UIFont fontNamesForFamilyName:]来列出系统中已知的所有字体名称。尝试打印出它们以查看系统期望的名称。示例代码:

static void dumpAllFonts() {
    for (NSString *familyName in [UIFont familyNames]) {
        for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
            NSLog(@"%@", fontName);
        }
    }
}

将它放入你的应用程序中,调用它,查看所得结果。如果在输出中看到一个适合你的字体的名称,请使用它。否则,可能是因为你没有正确地将字体添加到你的应用程序中。

在Swift中:

func dumpAllFonts() {
    for familyName in UIFont.familyNames {
        for fontName in UIFont.fontNames(forFamilyName: familyName) {
            print(fontName)
        }
    }
}

1
我检查了一下,我的字体不在那里。看起来这些文件没有被添加到资源中,所以我添加了它们,现在它们可以正常工作了,谢谢。 - Muhammad Umar
4
如果您想在Swift中进行检查: for familyName in UIFont.familyNames() { if let fn = familyName as? String { for font in UIFont.fontNamesForFamilyName(fn) { println("font: \(font)") } } } - Wojciech Rutkowski

53
尽管看起来UIFontfontNamed:size:方法对所提供的字体名称相当宽容,但官方的fontName始终是该字体的内部PostScript名称。字体的PostScript名称不能包含空格,通常用破折号替换它们。我不记得具体是什么了,但我认为它们可能还限制在31个字符以内。
确定在代码中应使用哪个名称非常简单。在iOS设备上双击要使用的字体,以在Font Book中打开它。如果字体尚未安装,请单击弹出窗口中的安装按钮。安装完成后,在字体列表中选择字体。在Font Book的菜单中,选择“预览”>“显示字体信息”。这将显示与下图中类似的字体信息: enter image description here 如您所见,Helvetica Neue LT Std 65 Medium的PostScript名称为HelveticaNeueLTStd-Md。这就是您在代码中应该使用的名称。
在应用程序的Info.plist文件中,需要使用字体本身的实际文件名,无论它是什么。在我的情况下,它是HelveticaNeueLTStd-Md.otf

作为对此的有趣扩展,如果您包含字体但名称不正确,Xcode将显示奇怪的行为。例如,我在我的plist中添加了“Sport World-Light”字体,但我实际上在我的项目中包含的字体文件是“Sports World-Regular”。应用程序正确加载了字体,即使我有错误的名称。它给了我一个奇怪的启动失败,但继续进行 - 在此处查看更多信息:https://dev59.com/YoTba4cB1Zd3GeqP0xKy - shortstuffsushi

51

这是第四步,如何在应用程序中添加自定义字体。

1-将.TTF字体文件添加到您的应用程序中
2-修改application-info.plist文件
3-添加键"Fonts provided by application"到新行中
4-并将每个.TTF文件(字体文件)添加到每行中。

另外,阅读教程以提高您的知识水平。

获取更多信息:

但是,在将字体添加到应用程序之后,有时字体名称可能与文件名不同,因此您需要应用/编写字体的真实名称,请查看@NSGod的答案。

以下是查找系统中所有字体的代码:

for(NSString *fontfamilyname in [UIFont familyNames])
{
    NSLog(@"Family:'%@'",fontfamilyname);
    for(NSString *fontName in [UIFont fontNamesForFamilyName:fontfamilyname])
    {
        NSLog(@"\tfont:'%@'",fontName);
    }
    NSLog(@"~~~~~~~~");
}

也许以上步骤和建议对您有所帮助:


6
这两种方法都不属于公共API。使用任何一种都会导致你的应用程序无法通过审核。 - rob mayoff
@"FontName" 没有扩展名。例如:UILabel *label; label.font = [UIFont fontWithName:@"MyriadPro-Light" size:36.0]; - Mazen Kasser
@rob 我不明白这个答案与你的答案有什么不同,因此为什么这个答案会导致应用程序被拒绝而你的不会。也许只是因为这是一年前的帖子之类的原因。但是在我使用了你的方法(已经打勾)来获取字体名称之前,直到我按照他在这里说的做法,我的字体才被包含在那个列表中。 - badweasel
你需要像这个答案建议的那样将字体添加到 application-info.plist 中。然而,在这个答案的示例代码中,他使用了两个私有方法:fontWithFamilyName:traits:size:fontWithMarkupDescription:。由于这两个方法都不是公共的 iOS SDK 的一部分,如果你的应用程序使用了它们,苹果很可能会拒绝你的应用程序。 - rob mayoff
@robmayoff - 谢谢你纠正我。当我写这个答案的时候,我真的不知道。 :) 你可以检查一下我的修改后的答案 :) 再次感谢 :) - iPatel

9

获取字体名称的简便方法

  1. 右键点击.ttf/.otf文件,选择“获取信息”
  2. 阅读全名属性,并将其用作字体名称

这适用于在信息.plist文件中(添加扩展名)和代码中使用[UIFont fontWithName:<Full Name> size:17]


1
这并不总是正确的。你应该选择后缀名而不是全名。 - iosMentalist
1
抱歉,这是错误的。文件名通常与字体名称相同,但并非总是如此。至于全名,我检查了一个麻烦的字体文件。全名为“Source Sans Pro Italic”;文件名为“SourceSansPro-Italic.ttf”;字体名称为“SourceSansPro-It”——请注意它们都不同。我刚刚浪费了很多时间在这上面。正确的方法是添加文件,将文件名添加到属性列表中,然后打印所有字体名称。另外,我也在我的字体文件上测试了全名,结果和预期一样行不通。 - n13
这应该是你的第一个猜测。如果不起作用,看看其他选项...你也可以通过在Mac OS X上打开FontBook来安装字体。 - Andrew
即使那不完全正确,它也指引我朝着正确的方向前进,救了我的一天。 - Leszek Zarna

3

其他答案没有问题。实际上,iPatel的前提条件仍然适用。

在Swift 2.2+中,显示姓氏的调用只需简单地执行以下操作:

  UIFont.familyNames().sort().forEach({ (familyName) in
            debugPrint(UIFont.fontNamesForFamilyName(familyName))
        })

如果你已经在系统中安装了字体,你也可以在Storyboard中的UI元素中简单地添加字体。
注意:
然而,在某些情况下,我注意到一个错误,即使将字体正确添加到项目、info.plist和Storyboard的UI元素中,它们仍然不能正确反映您所需的更改。在某些情况下,切换设置将有助于Storyboard同步其底层xml。在其他情况下,您可能需要在代码中更新自定义字体的大小,以使更改生效。我发现在Swift中最简单的方法是:
@IBOutlet weak var startMessage: UILabel!
startMessage.font = UIFont(name: startMessage.font.familyName, size: 31.0)

这种方法假设自定义字体已经在Storyboard中设置,并且只是通过代码更新字体大小。使用这种解决方法可以确保如果满足所有其他前提条件,实际上会看到正确的自定义字体。它还消除了实际上需要知道底层字体名称的需要(尽管如果需要,上面的初始Swift代码将给出名称)。


3

只需使用 NSLog 输出您想要获取的字体即可:

NSLog(@" %@", [UIFont fontNamesForFamilyName:@"American Typewriter"]);

然后您将获得一个数组:

(
  "AmericanTypewriter-CondensedLight",
  "AmericanTypewriter-Light",
  "AmericanTypewriter-Bold",
  AmericanTypewriter,
  "AmericanTypewriter-CondensedBold",
  "AmericanTypewriter-Condensed"
)

在代码中使用任何你需要的字体名称,例如AmericanTypewriter-Bold,可以写成:[UIFont fontWithName:@"AmericanTypewriter-Bold" size:12.0]

另外,你可以按字体族群对所有应用字体进行分组。

for (NSString* family in [UIFont familyNames])
{
    NSLog(@"%@", family);

    for (NSString* name in [UIFont fontNamesForFamilyName: family])
    {
        NSLog(@"  %@", name);
    }
}

3
我编写了一些代码,可以仅打印出你想要的字体名称,而不是打印所有字体。
- (NSString *)realNameOfFont:(NSString *)fullFontName {
    NSString *fontName = [[fullFontName componentsSeparatedByString:@"."] firstObject];
    NSString *ext = [fullFontName pathExtension];

    NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:fontName ofType:ext]];
    if (data == nil) {
        NSLog(@"Failed to load font. Data at path %@ is null", fullFontName);
        return nil;
    }
    CFErrorRef errorRef;
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
    CGFontRef font = CGFontCreateWithDataProvider(provider);
    NSString *realFontName = (__bridge NSString *)CGFontCopyPostScriptName(font);
    if (!CTFontManagerRegisterGraphicsFont(font, &errorRef)) {
        NSError *error = (__bridge NSError *)errorRef;
        if (error.code != kCTFontManagerErrorAlreadyRegistered) {
            NSLog(@"Failed to load font: %@", error);
        }
    }
    NSLog(@"Real font name: %@", realFontName);
    CFRelease(font);
    CFRelease(provider);
    return realFontName;
}

例子:

 NSArray *fonts = @[@"bg_en_AmaticSC-Bold111.otf", @"bg_en_segoescb_0.ttf", @"bg_en_UTM Cookies_2.ttf", @"bg_en_VSCOProximaExtrabold_0.otf"];
for (NSString *fontFullName in fonts) {
    [self realNameOfFont:fontFullName];
}

结果:

Failed to load font. Data at path bg_en_AmaticSC-Bold111.otf is null
Real font name: SegoeScript-Bold
Real font name: UTM-Cookies
Real font name: ProximaNova-Extrabld

3

Swift版本:

static func printAllFontNames() {
    for familyname in UIFont.familyNames() {
        for fname in UIFont.fontNamesForFamilyName(familyname) {
            print(fname)
        }
    }
}

1

更新至Swift 3

for familyname in UIFont.familyNames {
            for fname in UIFont.fontNames(forFamilyName: familyname) {
                print(fname)
            }
        }

1

Swift 3 版本:

UIFont.familyNames.sorted().forEach({ (familyName) in
            print(UIFont.fontNames(forFamilyName: familyName))
        })

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