在界面构建器中使用自定义字体

时间:2022-09-06 20:21:39

I've searched this site but I just found unanswered questions.

我搜索过这个网站,但我发现了一些未解决的问题。

I've loaded a custom font into my xcode project. A [UIFont fontWithName:@"Laconic-Light" size:19] works. But interface builder doesn't like the font. I can't use it with IB it always shows the default font. Is there a way to tell IB that its ok to use the font?

我已经将自定义字体加载到我的xcode项目中。一个[UIFont fontWithName:@“Laconic-Light”大小:19]有效。但是界面构建器不喜欢该字体。我无法与IB一起使用它总是显示默认字体。有没有办法告诉IB它可以使用该字体?

6 个解决方案

#1


63  

I have also this problem in Xcode 4. In my program, there are lots of UILabel which have no IBOutlets so I do in that way;

我在Xcode 4中也有这个问题。在我的程序中,有很多UILabel没有IBOutlets,所以我这样做;

First, subclass the UILabel to CustomFontLabel

首先,将UILabel子类化为CustomFontLabel

Then, override the "awakeFromNib" method

然后,覆盖“awakeFromNib”方法

@implementation CustomFontLabel

- (void)awakeFromNib {
    [super awakeFromNib];
    self.font = [UIFont fontWithName:@"CustomFontName" size:self.font.pointSize];
}

@end

Finally, in Interface Builder > Identity Inspector change class to CustomFontLabel.

最后,在Interface Builder> Identity Inspector中将类更改为CustomFontLabel。

#2


5  

Another solution would be to subclass UILabel to load in your custom font. You can then reference it in IB, although you still cannot see the proper font.

另一种解决方案是将UILabel子类化为加载自定义字体。然后,您可以在IB中引用它,尽管您仍然看不到正确的字体。

#3


3  

I prefer to do this in a slightly more generic way, which let's you size your text within Interface Builder, and simply replace the fonts at runtime.

我更喜欢以稍微更通用的方式执行此操作,这样您可以在Interface Builder中调整文本大小,并在运行时简单地替换字体。

I create an IBCollection property for any UIKit elements to set a font to, then wire up the appropriate items from IB.

我为任何UIKit元素创建一个IBCollection属性来设置字体,然后从IB连接相应的项目。

@property (strong, nonatomic) IBOutletCollection(id) NSArray *lightFontItems;
@property (strong, nonatomic) IBOutletCollection(id) NSArray *regularFontItems;

Then in my view did load I use a method like this:

然后在我看来加载我使用这样的方法:

[self setFontName:@"Roboto-Light" onItemsInArray:[self lightFontItems]];
[self setFontName:@"Roboto-Regular" onItemsInArray:[self regularFontItems]];

And the setLightFontOnItemsInArray: method looks like this:

setLightFontOnItemsInArray:方法如下所示:

+ (void)setFontName:(NSString *)fontName onItemsInArray:(NSArray *)array;
{
  [array each:^(id item) {
    if (![item respondsToSelector:@selector(setFont:)]) return;
    [item performSelector:@selector(setFont:) withObject:[UIFont fontWithName:fontName size:[[item font] pointSize]]];
  }];
}

#4


3  

You can install this script http://pitaya.ch/moarfonts/.

您可以安装此脚本http://pitaya.ch/moarfonts/。

Works really well for me with xcode 5.1.1.

xcode 5.1.1对我来说非常好用。

#5


3  

Thanks to apple, in Xcode 6, we have custom fonts available in interface builder itself.

感谢apple,在Xcode 6中,我们在界面构建器本身中提供了自定义字体。

  1. Add the .ttf font file to your bundle
  2. 将.ttf字体文件添加到您的包中
  3. Add the font name to the .plist file.
  4. 将字体名称添加到.plist文件中。
  5. Go to the xib/storyboard file, you can see your font.
  6. 转到xib / storyboard文件,您可以看到您的字体。

在界面构建器中使用自定义字体

#6


1  

Swizzle a Font

The solution is generally straightforward if you swizzle the UIFont class. I think it is best to pick a sane font like Helvetica Neue and override that. This allows you to put the whole project back into the standard by pulling the mapping. I had already come up with a swizzle to achieve this goal when I realized someone else did it too so I mashed it up a bit. As NSHipster will tell you swizzling can be dangerous, but in this case the risk is pretty low considering the absolute simplicity of the UIFont API. In my case it was done for an Enterprise app so it was even lower risk.

如果您调用UIFont类,解决方案通常很简单。我认为最好选择像Helvetica Neue这样的理智字体并覆盖它。这允许您通过拉动映射将整个项目重新置于标准中。当我意识到其他人也这样做的时候,我已经想出了一个实现这个目标的调酒,所以我把它搞砸了一下。正如NSHipster会告诉你,调配可能很危险,但在这种情况下,考虑到UIFont API的绝对简单性,风险相当低。在我的情况下,它是为企业应用程序完成的,因此风险更低。

UIFont+CustomFont.m Category

#import <objc/runtime.h>

static NSString *const kFontMapPlist = @"FontMap";
static NSDictionary *_replacementFontDictionary = nil;



@implementation UIFont (CustomFont)


static void initializeReplacementFonts()
{
    static BOOL initialized = NO;
    if (initialized)
        return;
    initialized = YES;

    // A Plist with a Dictionary from->to font name mapping
    NSURL *replacementFontMapURL = [[NSBundle mainBundle] URLForResource:kFontMapPlist withExtension:@"plist"];
    NSDictionary *replacementFontMap = [NSDictionary dictionaryWithContentsOfURL:replacementFontMapURL];
    [UIFont setReplacementFontDictionary:replacementFontMap];
}

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        initializeReplacementFonts();

        SEL fontWithNameSizeSelector = @selector(fontWithName:size:);
        SEL swizzledFontWithNameSizeSelector = @selector(clp_fontWithName:size:);
        SwizzleClassMethod([UIFont class], fontWithNameSizeSelector, swizzledFontWithNameSizeSelector);

        SEL fontWithDescriptorSizeSelector = @selector(fontWithDescriptor:size:);
        SEL swizzledfontWithDescriptorSelector = @selector(clp_fontWithDescriptor:size:);
        SwizzleClassMethod([UIFont class], fontWithDescriptorSizeSelector, swizzledfontWithDescriptorSelector);
    });
}

void SwizzleClassMethod(Class class, SEL originalSelector, SEL replacementSelector)
{
    Class clazz = objc_getMetaClass(class_getName(class));

    Method originalMethod = class_getClassMethod(clazz, originalSelector);
    Method replacementMethod = class_getClassMethod(clazz, replacementSelector);

    // Add method if it doesn't eixst
    BOOL didAddMethod =
    class_addMethod(clazz,
                    originalSelector,
                    method_getImplementation(replacementMethod),
                    method_getTypeEncoding(replacementMethod));


    if (didAddMethod) {
        class_replaceMethod(clazz,
                            replacementSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, replacementMethod);
    }
}



#pragma mark - Swizzled font by descriptor and name calls

+ (UIFont *)clp_fontWithDescriptor:(UIFontDescriptor *)descriptor size:(CGFloat)pointSize
{
    NSString *originalFontName = descriptor.fontAttributes[UIFontDescriptorNameAttribute];
    NSString *replacementFontName = _replacementFontDictionary[originalFontName];

    UIFontDescriptor *replacementFontDescriptor = descriptor;
    if (replacementFontName != nil) {
        replacementFontDescriptor = [UIFontDescriptor fontDescriptorWithFontAttributes:@{UIFontDescriptorNameAttribute: replacementFontName}];
    }

    return [self clp_fontWithDescriptor:replacementFontDescriptor size:pointSize];
}

+ (UIFont *)clp_fontWithName:(NSString *)fontName size:(CGFloat)fontSize
{
    NSString *replacementFontName = _replacementFontDictionary[fontName];
    if (replacementFontName == nil) {
        replacementFontName = fontName;
    }

    return [self clp_fontWithName:replacementFontName size:fontSize];
}



#pragma mark - Replacement Dictionary Getter and Setter

+ (NSDictionary *)replacementDictionary
{
    return _replacementFontDictionary;
}

+ (void)setReplacementFontDictionary:(NSDictionary *)replacmentFontDictionary
{
    if (replacmentFontDictionary == _replacementFontDictionary) {
        return;
    }

    _replacementFontDictionary = replacmentFontDictionary;

    // Validate font existence.
    for (NSString *originalFontName in [_replacementFontDictionary allKeys]) {
        NSString *replacementFontName = [_replacementFontDictionary objectForKey:originalFontName];
        UIFont *replacementFont = [UIFont fontWithName:replacementFontName size:10.0f];
        if (replacementFont == nil) {
            DDLogError(@"WARNING: replacement font '%@' is not available.", replacementFontName);
        }
    }
}

@end

The FontMap.plist

For the sake of simplicity we'll pretend we have a font called CustomSans.

为了简单起见,我们假装我们有一个名为CustomSans的字体。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>HelveticaNeue-Light</key>
    <string>CustomSans-Light</string>
    <key>HelveticaNeue-LightItalic</key>
    <string>CustomSans-LightItalic</string>
    <key>HelveticaNeue-Bold</key>
    <string>CustomSans-Bold</string>
    <key>HelveticaNeue-BoldItalic</key>
    <string>CustomSans-BoldItalic</string>
</dict>
</plist>

#1


63  

I have also this problem in Xcode 4. In my program, there are lots of UILabel which have no IBOutlets so I do in that way;

我在Xcode 4中也有这个问题。在我的程序中,有很多UILabel没有IBOutlets,所以我这样做;

First, subclass the UILabel to CustomFontLabel

首先,将UILabel子类化为CustomFontLabel

Then, override the "awakeFromNib" method

然后,覆盖“awakeFromNib”方法

@implementation CustomFontLabel

- (void)awakeFromNib {
    [super awakeFromNib];
    self.font = [UIFont fontWithName:@"CustomFontName" size:self.font.pointSize];
}

@end

Finally, in Interface Builder > Identity Inspector change class to CustomFontLabel.

最后,在Interface Builder> Identity Inspector中将类更改为CustomFontLabel。

#2


5  

Another solution would be to subclass UILabel to load in your custom font. You can then reference it in IB, although you still cannot see the proper font.

另一种解决方案是将UILabel子类化为加载自定义字体。然后,您可以在IB中引用它,尽管您仍然看不到正确的字体。

#3


3  

I prefer to do this in a slightly more generic way, which let's you size your text within Interface Builder, and simply replace the fonts at runtime.

我更喜欢以稍微更通用的方式执行此操作,这样您可以在Interface Builder中调整文本大小,并在运行时简单地替换字体。

I create an IBCollection property for any UIKit elements to set a font to, then wire up the appropriate items from IB.

我为任何UIKit元素创建一个IBCollection属性来设置字体,然后从IB连接相应的项目。

@property (strong, nonatomic) IBOutletCollection(id) NSArray *lightFontItems;
@property (strong, nonatomic) IBOutletCollection(id) NSArray *regularFontItems;

Then in my view did load I use a method like this:

然后在我看来加载我使用这样的方法:

[self setFontName:@"Roboto-Light" onItemsInArray:[self lightFontItems]];
[self setFontName:@"Roboto-Regular" onItemsInArray:[self regularFontItems]];

And the setLightFontOnItemsInArray: method looks like this:

setLightFontOnItemsInArray:方法如下所示:

+ (void)setFontName:(NSString *)fontName onItemsInArray:(NSArray *)array;
{
  [array each:^(id item) {
    if (![item respondsToSelector:@selector(setFont:)]) return;
    [item performSelector:@selector(setFont:) withObject:[UIFont fontWithName:fontName size:[[item font] pointSize]]];
  }];
}

#4


3  

You can install this script http://pitaya.ch/moarfonts/.

您可以安装此脚本http://pitaya.ch/moarfonts/。

Works really well for me with xcode 5.1.1.

xcode 5.1.1对我来说非常好用。

#5


3  

Thanks to apple, in Xcode 6, we have custom fonts available in interface builder itself.

感谢apple,在Xcode 6中,我们在界面构建器本身中提供了自定义字体。

  1. Add the .ttf font file to your bundle
  2. 将.ttf字体文件添加到您的包中
  3. Add the font name to the .plist file.
  4. 将字体名称添加到.plist文件中。
  5. Go to the xib/storyboard file, you can see your font.
  6. 转到xib / storyboard文件,您可以看到您的字体。

在界面构建器中使用自定义字体

#6


1  

Swizzle a Font

The solution is generally straightforward if you swizzle the UIFont class. I think it is best to pick a sane font like Helvetica Neue and override that. This allows you to put the whole project back into the standard by pulling the mapping. I had already come up with a swizzle to achieve this goal when I realized someone else did it too so I mashed it up a bit. As NSHipster will tell you swizzling can be dangerous, but in this case the risk is pretty low considering the absolute simplicity of the UIFont API. In my case it was done for an Enterprise app so it was even lower risk.

如果您调用UIFont类,解决方案通常很简单。我认为最好选择像Helvetica Neue这样的理智字体并覆盖它。这允许您通过拉动映射将整个项目重新置于标准中。当我意识到其他人也这样做的时候,我已经想出了一个实现这个目标的调酒,所以我把它搞砸了一下。正如NSHipster会告诉你,调配可能很危险,但在这种情况下,考虑到UIFont API的绝对简单性,风险相当低。在我的情况下,它是为企业应用程序完成的,因此风险更低。

UIFont+CustomFont.m Category

#import <objc/runtime.h>

static NSString *const kFontMapPlist = @"FontMap";
static NSDictionary *_replacementFontDictionary = nil;



@implementation UIFont (CustomFont)


static void initializeReplacementFonts()
{
    static BOOL initialized = NO;
    if (initialized)
        return;
    initialized = YES;

    // A Plist with a Dictionary from->to font name mapping
    NSURL *replacementFontMapURL = [[NSBundle mainBundle] URLForResource:kFontMapPlist withExtension:@"plist"];
    NSDictionary *replacementFontMap = [NSDictionary dictionaryWithContentsOfURL:replacementFontMapURL];
    [UIFont setReplacementFontDictionary:replacementFontMap];
}

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        initializeReplacementFonts();

        SEL fontWithNameSizeSelector = @selector(fontWithName:size:);
        SEL swizzledFontWithNameSizeSelector = @selector(clp_fontWithName:size:);
        SwizzleClassMethod([UIFont class], fontWithNameSizeSelector, swizzledFontWithNameSizeSelector);

        SEL fontWithDescriptorSizeSelector = @selector(fontWithDescriptor:size:);
        SEL swizzledfontWithDescriptorSelector = @selector(clp_fontWithDescriptor:size:);
        SwizzleClassMethod([UIFont class], fontWithDescriptorSizeSelector, swizzledfontWithDescriptorSelector);
    });
}

void SwizzleClassMethod(Class class, SEL originalSelector, SEL replacementSelector)
{
    Class clazz = objc_getMetaClass(class_getName(class));

    Method originalMethod = class_getClassMethod(clazz, originalSelector);
    Method replacementMethod = class_getClassMethod(clazz, replacementSelector);

    // Add method if it doesn't eixst
    BOOL didAddMethod =
    class_addMethod(clazz,
                    originalSelector,
                    method_getImplementation(replacementMethod),
                    method_getTypeEncoding(replacementMethod));


    if (didAddMethod) {
        class_replaceMethod(clazz,
                            replacementSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, replacementMethod);
    }
}



#pragma mark - Swizzled font by descriptor and name calls

+ (UIFont *)clp_fontWithDescriptor:(UIFontDescriptor *)descriptor size:(CGFloat)pointSize
{
    NSString *originalFontName = descriptor.fontAttributes[UIFontDescriptorNameAttribute];
    NSString *replacementFontName = _replacementFontDictionary[originalFontName];

    UIFontDescriptor *replacementFontDescriptor = descriptor;
    if (replacementFontName != nil) {
        replacementFontDescriptor = [UIFontDescriptor fontDescriptorWithFontAttributes:@{UIFontDescriptorNameAttribute: replacementFontName}];
    }

    return [self clp_fontWithDescriptor:replacementFontDescriptor size:pointSize];
}

+ (UIFont *)clp_fontWithName:(NSString *)fontName size:(CGFloat)fontSize
{
    NSString *replacementFontName = _replacementFontDictionary[fontName];
    if (replacementFontName == nil) {
        replacementFontName = fontName;
    }

    return [self clp_fontWithName:replacementFontName size:fontSize];
}



#pragma mark - Replacement Dictionary Getter and Setter

+ (NSDictionary *)replacementDictionary
{
    return _replacementFontDictionary;
}

+ (void)setReplacementFontDictionary:(NSDictionary *)replacmentFontDictionary
{
    if (replacmentFontDictionary == _replacementFontDictionary) {
        return;
    }

    _replacementFontDictionary = replacmentFontDictionary;

    // Validate font existence.
    for (NSString *originalFontName in [_replacementFontDictionary allKeys]) {
        NSString *replacementFontName = [_replacementFontDictionary objectForKey:originalFontName];
        UIFont *replacementFont = [UIFont fontWithName:replacementFontName size:10.0f];
        if (replacementFont == nil) {
            DDLogError(@"WARNING: replacement font '%@' is not available.", replacementFontName);
        }
    }
}

@end

The FontMap.plist

For the sake of simplicity we'll pretend we have a font called CustomSans.

为了简单起见,我们假装我们有一个名为CustomSans的字体。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>HelveticaNeue-Light</key>
    <string>CustomSans-Light</string>
    <key>HelveticaNeue-LightItalic</key>
    <string>CustomSans-LightItalic</string>
    <key>HelveticaNeue-Bold</key>
    <string>CustomSans-Bold</string>
    <key>HelveticaNeue-BoldItalic</key>
    <string>CustomSans-BoldItalic</string>
</dict>
</plist>