在界面生成器中使用自定义字体

发布于 2024-10-05 07:01:32 字数 181 浏览 5 评论 0原文

我搜索过该网站,但发现了一些未解答的问题。

我已将自定义字体加载到我的 xcode 项目中。 [UIFont fontWithName:@"Laconic-Light" size:19] 有效。但界面生成器不喜欢这种字体。我不能将它与 IB 一起使用,它总是显示默认字体。有没有办法告诉IB可以使用该字体?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

我不吻晚风 2024-10-12 07:01:32

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

首先,将 UILabel 子类化为 CustomFontLabel

然后,重写“awakeFromNib”方法

@implementation CustomFontLabel

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

@end

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

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;

First, subclass the UILabel to CustomFontLabel

Then, override the "awakeFromNib" method

@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.

瑾夏年华 2024-10-12 07:01:32

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

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.

划一舟意中人 2024-10-12 07:01:32

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

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

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

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

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

并且 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]]];
  }];
}

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.

I create an IBCollection property for any UIKit elements to set a font to, then wire up the appropriate items from 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:

+ (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]]];
  }];
}
枯寂 2024-10-12 07:01:32

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

我在 xcode 5.1.1 上工作得非常好。

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

Works really well for me with xcode 5.1.1.

赏烟花じ飞满天 2024-10-12 07:01:32

感谢苹果,在 Xcode 6 中,我们在界面生成器本身中提供了自定义字体。

  1. 将 .ttf 字体文件添加到捆绑包中
  2. 将字体名称添加到 .plist 文件中。
  3. 转到 xib/storyboard 文件,您可以看到您的字体。

输入图片此处描述

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

  1. Add the .ttf font file to your bundle
  2. Add the font name to the .plist file.
  3. Go to the xib/storyboard file, you can see your font.

enter image description here

一生独一 2024-10-12 07:01:32

调配字体

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

UIFont+CustomFont.m 类别

#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

FontMap.plist

为了简单起见,我们假设我们有一种名为 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>

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+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.

<?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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文