精简加载自定义字体

效果图:

核心源码:

UIFont+WDCustomLoader.m 与 UIFont+WDCustomLoader.h

//
//  UIFont+WDCustomLoader.h
//
//  Created by Walter Da Col on 10/17/13.
//  Copyright (c) 2013 Walter Da Col (walter.dacol<at>gmail.com)
//

#import <UIKit/UIKit.h>

/**
 You can use `UIFont+WDCustomLoader` category to load custom fonts for your
 application without worring about plist or real font names.
 */
@interface UIFont (WDCustomLoader)

/// @name Implicit registration and font loading

/**
 Get `UIFont` object for the selected font file.

 This method calls `+customFontWithURL:size`.

 @deprecated
 @see +customFontWithURL:size: method
 @param size Font size
 @param name Font filename without extension
 @param extension Font filename extension (@"ttf" and @"otf" are supported)
 @return `UIFont` object or `nil` on errors
 */
+ (UIFont *) customFontOfSize:(CGFloat)size withName:(NSString *)name withExtension:(NSString *)extension;

/**
 Get `UIFont` object for the selected font file (*.ttf or *.otf files).

 The first call of this method will register the font using
 `+registerFontFromURL:` method.

 @see +registerFontFromURL: method
 @param fontURL Font file absolute url
 @param size Font size
 @return `UIFont` object or `nil` on errors
 */
+ (UIFont *) customFontWithURL:(NSURL *)fontURL size:(CGFloat)size;

/// @name Explicit registration

/**
 Allow custom fonts registration.

 With this method you can load all supported font file: ttf, otf, ttc and otc.
 Font that are already registered, with this library or by system, will not be
 registered and you will see a warning log.

 @param fontURL Font file absolute url
 @return An array of postscript name which represent the file‘s font(s) or `nil`
 on errors. (With iOS < 7 as target you will see an empty array for collections)
 */
+ (NSArray *) registerFontFromURL:(NSURL *)fontURL;

@end
//
//  UIFont+WDCustomLoader.m
//
//  Created by Walter Da Col on 10/17/13.
//  Copyright (c) 2013 Walter Da Col (walter.dacol<at>gmail.com)
//

#import "UIFont+WDCustomLoader.h"
#import <CoreText/CoreText.h>

// Feature and deployment target check
#if  ! __has_feature(objc_arc)
#error This file must be compiled with ARC.
#endif

#if __IPHONE_OS_VERSION_MIN_REQUIRED < 40100
#error This file must be compiled with Deployment Target greater or equal to 4.1
#endif

// Activate Xcode only logging
#ifdef DEBUG
#define UIFontWDCustomLoaderDLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define UIFontWDCustomLoaderDLog(...)
#endif

@implementation UIFont (Custom)
static CGFloat const kSizePlaceholder = 1.0f;
static NSMutableDictionary *appRegisteredCustomFonts = nil;

/**
 Check features for full font collections support

 @return YES if all features are supported
 */
+ (BOOL) deviceHasFullSupportForFontCollections {

    return (CTFontManagerCreateFontDescriptorsFromURL != NULL); // 10.6 or 7.0

}

/**
 Inner method for font(s) registration from a file

 @param fontURL A font URL

 @return Registration result
 */
+ (BOOL) registerFromURL:(NSURL *)fontURL {

    CFErrorRef error;
    BOOL registrationResult = YES;

    registrationResult = CTFontManagerRegisterFontsForURL((__bridge CFURLRef)fontURL, kCTFontManagerScopeProcess, &error);

    if (!registrationResult) {
        UIFontWDCustomLoaderDLog(@"Error with font registration: %@", error);
        CFRelease(error);
        return NO;
    }

    return YES;
}

/**
 Inner method for font registration from a graphic font.

 @param fontRef A CGFontRef

 @return Registration result
 */
+ (BOOL) registerFromCGFont:(CGFontRef)fontRef {

    CFErrorRef error;
    BOOL registrationResult = YES;

    registrationResult = CTFontManagerRegisterGraphicsFont(fontRef, &error);

    if (!registrationResult) {
        UIFontWDCustomLoaderDLog(@"Error with font registration: %@", error);
        CFRelease(error);
        return NO;
    }

    return YES;

}

+ (NSArray *) registerFontFromURL:(NSURL *)fontURL {
    // Dictionary creation
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        appRegisteredCustomFonts = [NSMutableDictionary new];
    });

    // Result
    NSArray *fontPSNames = nil;

    // Critical section
    @synchronized(appRegisteredCustomFonts) {

        // Check if this library knows this url
        fontPSNames = [[appRegisteredCustomFonts objectForKey:fontURL] copy];

        if (fontPSNames == nil) {

            // Check features
            if ([UIFont deviceHasFullSupportForFontCollections]) {

                // Retrieve font descriptors from ttf, otf, ttc and otc files
                NSArray *fontDescriptors = (__bridge_transfer NSArray *)(CTFontManagerCreateFontDescriptorsFromURL((__bridge CFURLRef)fontURL));

                // Check errors
                if (fontDescriptors) {

                    // Check how many fonts are already registered (or have the
                    // same name of another font)
                    NSMutableArray *verifiedFontPSNames = [NSMutableArray new];

                    for (NSDictionary *fontDescriptor in fontDescriptors) {
                        NSString *fontPSName = [fontDescriptor objectForKey:@"NSFontNameAttribute"];

                        if (fontPSName) {
                            if ([UIFont fontWithName:fontPSName size:kSizePlaceholder]) {
                                UIFontWDCustomLoaderDLog(@"Warning with font registration: Font ‘%@‘ already registered",fontPSName);
                            }
                            [verifiedFontPSNames addObject:fontPSName];
                        }
                    }

                    fontPSNames = [NSArray arrayWithArray:verifiedFontPSNames];

                    // At least one
                    if ([fontPSNames count] > 0) {

                        // If registration went ok
                        if ([UIFont registerFromURL:fontURL]) {
                            // Add url to this library
                            [appRegisteredCustomFonts setObject:fontPSNames
                                                         forKey:fontURL];

                        } else {
                            fontPSNames = nil;
                        }

                    } else { // [fontPSNames count] <= 0
                        UIFontWDCustomLoaderDLog(@"Warning with font registration: All fonts in ‘%@‘ are already registered", fontURL);
                    }

                } else { // CTFontManagerCreateFontDescriptorsFromURL fail
                    UIFontWDCustomLoaderDLog(@"Error with font registration: File ‘%@‘ is not a Font", fontURL);
                    fontPSNames = nil;
                }
            } else { // [UIFont deviceHasFullSupportForFontCollections] fail

                // Read data
                NSError *error;
                NSData *fontData = [NSData dataWithContentsOfURL:fontURL
                                                         options:NSDataReadingUncached
                                                           error:&error];

                // Check data creation
                if (fontData) {

                    // Load font
                    CGDataProviderRef fontDataProvider = CGDataProviderCreateWithCFData((CFDataRef)fontData);
                    CGFontRef loadedFont = CGFontCreateWithDataProvider(fontDataProvider);

                    // Check font
                    if (loadedFont != NULL) {

                        // Prior to iOS7 is not easy to retrieve names from font collections
                        // But is possible to register collections
                        NSSet *singleFontValidExtensions = [NSSet setWithArray:@[@"ttf", @"otf"]];

                        if ([singleFontValidExtensions containsObject:[fontURL pathExtension]]) {
                            // Read name
                            fontPSNames = @[(__bridge_transfer NSString *)(CGFontCopyPostScriptName(loadedFont))];

                            // Check if registration is required
                            if ([UIFont fontWithName:fontPSNames[0] size:kSizePlaceholder] == nil) {

                                // If registration went ok
                                if ([UIFont registerFromCGFont:loadedFont]) {
                                    // Add url to this library
                                    [appRegisteredCustomFonts setObject:fontPSNames
                                                                 forKey:fontURL];

                                } else {
                                    fontPSNames = nil;
                                }
                            } else {
                                UIFontWDCustomLoaderDLog(@"Warning with font registration: All fonts in ‘%@‘ are already registered", fontURL);
                            }

                        } else {
                            // Is a collection

                            //TODO find a way to read names
                            fontPSNames = @[];

                            // Revert to url registration which allow collections
                            // If registration went ok
                            if ([UIFont registerFromURL:fontURL]) {
                                // Add url to this library
                                [appRegisteredCustomFonts setObject:fontPSNames
                                                             forKey:fontURL];

                            } else {
                                fontPSNames = nil;
                            }
                        }

                    } else { // CGFontCreateWithDataProvider fail
                        UIFontWDCustomLoaderDLog(@"Error with font registration: File ‘%@‘ is not a Font", fontURL);
                        fontPSNames = nil;
                    }

                    // Release
                    CGFontRelease(loadedFont);
                    CGDataProviderRelease(fontDataProvider);
                } else {
                    UIFontWDCustomLoaderDLog(@"Error with font registration: URL ‘%@‘ cannot be read with error: %@", fontURL, error);
                    fontPSNames = nil;
                }

            }

        }

    }

    return fontPSNames;
}

+ (UIFont *) customFontWithURL:(NSURL *)fontURL size:(CGFloat)size {

    // Only single font with this method
    NSSet *singleFontValidExtensions = [NSSet setWithArray:@[@"ttf", @"otf"]];

    if (![singleFontValidExtensions containsObject:[fontURL pathExtension]]) {
        UIFontWDCustomLoaderDLog(@"Only ttf or otf files are supported by this method");
        return nil;
    }

    NSArray *fontPSNames = [UIFont registerFontFromURL:fontURL];

    if (fontPSNames == nil) {
        UIFontWDCustomLoaderDLog(@"Invalid Font URL: %@", fontURL);
        return nil;
    }
    if ([fontPSNames count] != 1) {
        UIFontWDCustomLoaderDLog(@"Font collections not supported by this method");
        return nil;
    }
    return [UIFont fontWithName:fontPSNames[0] size:size];
}

+ (UIFont *) customFontOfSize:(CGFloat)size withName:(NSString *)name withExtension:(NSString *)extension {
    // Get url for font resource
    NSURL *fontURL = [[[NSBundle mainBundle] URLForResource:name withExtension:extension] absoluteURL];

    return [UIFont customFontWithURL:fontURL size:size];
}

@end

以下源码都是本人在上述源码基础上封装的:

FontInfo.h 与 FontInfo.m

//
//  FontInfo.h
//  GCD
//
//  Created by YouXianMing on 14-9-21.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface FontInfo : NSObject

+ (NSDictionary *)customFontNameList;
+ (NSDictionary *)systomFontNameList;
+ (void)registerFont:(NSString *)fontPath withName:(NSString *)name;

@end
//
//  FontInfo.m
//  GCD
//
//  Created by YouXianMing on 14-9-21.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "FontInfo.h"
#import "UIFont+WDCustomLoader.h"

static NSMutableDictionary   *customFontDictionary = nil; // 自己加载的字体信息
static NSMutableDictionary   *systemFontDictionary = nil; // 系统字体信息

@implementation FontInfo

+ (void)initialize
{
    if (self == [FontInfo class])
    {
        customFontDictionary = [[NSMutableDictionary alloc] init];
        systemFontDictionary = [[NSMutableDictionary alloc] init];

        // 获取系统字体族
        [FontInfo getSystemFontList];
    }
}

+ (void)getSystemFontList
{
    NSArray *familyNames = [UIFont familyNames];
    for( NSString *familyName in familyNames)
    {
        NSArray *fontNames = [UIFont fontNamesForFamilyName:familyName];
        [systemFontDictionary setObject:fontNames forKey:familyName];
    }
}

+ (void)registerFont:(NSString *)fontPath withName:(NSString *)name
{
    NSArray *nameArray = [UIFont registerFontFromURL:[NSURL fileURLWithPath:fontPath]];
    [customFontDictionary setObject:nameArray forKey:name];
}

+ (NSDictionary *)customFontNameList
{
    return [NSDictionary dictionaryWithDictionary:customFontDictionary];
}

+ (NSDictionary *)systomFontNameList
{
    return [NSDictionary dictionaryWithDictionary:systemFontDictionary];
}

@end

UIFont+Custom.h 与 UIFont+Custom.m

//
//  UIFont+Custom.h
//  GCD
//
//  Created by YouXianMing on 14-9-21.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIFont (CustomFont)

+ (void)registerFontFamily:(NSString *)fontPath withName:(NSString *)name;
+ (NSDictionary *)systomAllFontsFamilyInfo;

@end
//
//  UIFont+Custom.m
//  GCD
//
//  Created by YouXianMing on 14-9-21.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "UIFont+CustomFont.h"
#import "FontInfo.h"

#ifdef DEBUG
#define UIFontCustomFontDLog(fmt, ...) NSLog((@"%@[%d]:%s:" fmt),[[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, __func__, ##__VA_ARGS__);
#else
#define UIFontCustomFontDLog(...)
#endif

@implementation UIFont (CustomFont)

+ (void)registerFontFamily:(NSString *)fontPath withName:(NSString *)name
{
    if (fontPath == nil) {
        UIFontCustomFontDLog(@"[警告]fontPath为空");
        return;
    }

    [FontInfo registerFont:fontPath withName:name];
}

+ (NSDictionary *)systomAllFontsFamilyInfo
{
    return [FontInfo systomFontNameList];
}

@end

NSString+CustomFont.h 与 NSString+CustomFont.m

//
//  NSString+CustomFont.h
//  GCD
//
//  Created by YouXianMing on 14-9-21.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import <Foundation/Foundation.h>

/*
 NSString值都为字体族名字
 */

/*
 经典字体家族
 "Helvetica Neue" =     (
 "HelveticaNeue-BoldItalic",
 "HelveticaNeue-Light",
 "HelveticaNeue-Italic",
 "HelveticaNeue-UltraLightItalic",
 "HelveticaNeue-CondensedBold",
 "HelveticaNeue-MediumItalic",
 "HelveticaNeue-Thin",
 "HelveticaNeue-Medium",
 "HelveticaNeue-ThinItalic",
 "HelveticaNeue-LightItalic",
 "HelveticaNeue-UltraLight",
 "HelveticaNeue-Bold",
 HelveticaNeue,
 "HelveticaNeue-CondensedBlack"
 );
 */

@interface NSString (CustomFont)

- (NSString *)customFontFamilyName;
- (NSString *)customFontFamilyNameAtIndex:(NSInteger)index;
- (NSArray *)customFontInfo;

- (NSString *)systemFontFamilyName;
- (NSString *)systemFontFamilyNameIndex:(NSInteger)index;
- (NSArray *)systemFontInfo;

@end
//
//  NSString+CustomFont.m
//  GCD
//
//  Created by YouXianMing on 14-9-21.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "NSString+CustomFont.h"
#import "FontInfo.h"

@implementation NSString (CustomFont)

#pragma public
- (NSString *)customFontFamilyName
{
    return [self fontFamilyName:self customFontIndex:0];
}

- (NSString *)customFontFamilyNameAtIndex:(NSInteger)index
{
    return [self fontFamilyName:self customFontIndex:index];
}

- (NSArray *)customFontInfo
{
    NSDictionary *fontDic = [FontInfo customFontNameList];
    if (self) {
        return fontDic[self];
    } else {
        return nil;
    }
}

- (NSString *)systemFontFamilyName
{
    return [self fontFamilyName:self systemFontIndex:0];
}

- (NSString *)systemFontFamilyNameIndex:(NSInteger)index
{
    return [self fontFamilyName:self systemFontIndex:index];
}

- (NSArray *)systemFontInfo
{
    NSDictionary *fontDic = [FontInfo systomFontNameList];
    if (self) {
        return fontDic[self];
    } else {
        return nil;
    }
}

#pragma private
- (NSString *)fontFamilyName:(NSString *)fontName customFontIndex:(NSInteger)index
{
    if (fontName == nil) {
        return nil;
    }

    NSDictionary *fontDic = [FontInfo customFontNameList];
    NSArray *fontIndex = fontDic[fontName];

    if (fontIndex) {
        return fontIndex[index];
    } else {
        return nil;
    }
}

- (NSString *)fontFamilyName:(NSString *)fontName systemFontIndex:(NSInteger)index
{
    if (fontName == nil) {
        return nil;
    }

    NSDictionary *fontDic = [FontInfo systomFontNameList];
    NSArray *fontIndex = fontDic[fontName];

    if (fontIndex) {
        return fontIndex[index];
    } else {
        return nil;
    }
}

@end

以下是使用源码:

//
//  RootViewController.m
//  GCD
//
//  Created by YouXianMing on 14-9-21.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "RootViewController.h"
#import "NSString+CustomFont.h"
#import "UIFont+CustomFont.h"

@interface RootViewController ()

@end

@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blackColor];

    // 注册自定义字体
    [UIFont registerFontFamily:[@"新蒂小丸子小学版.ttf" bundleFile]
                      withName:@"新蒂小丸子小学版"];

    // 显示
    UILabel *label_1      = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 200, 40)];
    label_1.text          = @"游贤明";
    label_1.textColor     = [UIColor redColor];
    label_1.textAlignment = NSTextAlignmentCenter;
    label_1.font          = [UIFont fontWithName:[@"新蒂小丸子小学版" customFontFamilyName] size:30.f];
    [self.view addSubview:label_1];

    UILabel *label_2      = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 40)];
    label_2.text          = @"YouXianMing";
    label_2.textColor     = [UIColor whiteColor];
    label_2.textAlignment = NSTextAlignmentCenter;
    label_2.font          = [UIFont fontWithName:[@"Helvetica Neue" systemFontFamilyNameIndex:1] size:18.f];
    [self.view addSubview:label_2];

    // 打印字体族信息
    NSLog(@"%@", [@"新蒂小丸子小学版" customFontInfo]);
    NSLog(@"%@", [@"Helvetica Neue" systemFontFamilyNameIndex:1]);
}

@end

使用注意事项:

时间: 2024-10-17 15:10:19

精简加载自定义字体的相关文章

ThinkPHP加载自定义的外部文件和配置文件

我们知道ThinkPHP有公共的函数文件和配置文件,位于Common目录下,默认Common/function.php为公共的函数文 件,Conf/config.php为公共配置文件.好了,那么如何自定义其他的公共函数和配置文件呢.这里不得不讲到两个配置参数 LOAD_EXT_FILE和LOAD_EXT_CONFIG了. 1. LOAD_EXT_FILE配置的是自定义的函数文件,比如我想在Common目录下再创建一个common.php文件,那么在config.php里 则可以配置LOAD_EX

[Yii2.0] 以Yii 2.0风格加载自定义类或命名空间 [配置使用Yii2 autoloader]

Yii 2.0最显著的特征之一就是引入了命名空间,因此对于自定义类的引入方式也同之前有所不同.这篇文章讨论一下如何利用Yii 2.0的自动加载机制,向系统中引入自定义类和命名空间.本文旨在抛砖引玉,如果有理解不当敬请指正,欢迎大家把自己的方法拿出来分享.我们希望被引入的类应该达成一下两点: 在应用中的任这里输入代码意位置可以使用该类名或命名空间,而不用显式调用require()/include(). 利用Yii的autoloader,仅在类被调用时加载,以遵循Yii按需加载的原则,节省资源. 我

Android中layout.xml文件中加载自定义的View类

<com.bn.summer.GGView3 android:layout_width="100dip" android:layout_height="114dip" android:layout_marginLeft="11dip" /> View类的实现: package com.bn.summer; import android.content.Context; import android.content.res.Resour

基于.net 的加载自定义配置-误操作

有时候 需要 将程序加载自定义的配置文件,除了自己写解析xml文件.内置的ConfigutionManager对象 是个不错的选项. 按照 app.config 的方式,做一个副本.然后从你的配置文件中,加载指定的配置 键值对! //方法1-可以读取任意位置的xml文件 ExeConfigurationFileMap filemap = new ExeConfigurationFileMap(); filemap.ExeConfigFilename = QuartzConfigPath; //f

rails 中加载自定义文件

rails默认生成lib文件夹,但是没有默认加载lib中的文件,可以在config/application.rb中配置如下代码,加载lib文件夹里面定义的module或者是class: config.autoload_paths += %W(#{config.root}/lib) 当然这种方法不只是可以加载lib文件,还可以加载其他自定义的文件夹. 注意的是这些自定义的文件的module或者class名一定要和文件名一直,比如class名为AppStore,那文件名一定要是app_store.r

加载自定义 cell 的 XIB 文件 的两种方式

自定义单元格如果是使用 IB  方式创建的,则需要手动加载,因为 XIB 上的 cell 不会自动加载 第一种:使用应用程序束 应用程序束 NSBundle:获得工程中所有的资源的路径,相当于当前工程的目录. //获得指定的xib中所有的视图 NSArray * array =  [[NSBundle mainBundle] loadNibNamed:@"ZYTableViewCell" owner:nil options:nil]; 注意通过应用程序束获得返回值是 XIB 文件中所有

利用@font-face加载Web字体

1.简介 @font-face用于自定义字体样式,从服务器端取得字体样式,使浏览器可以显示客户端并不存在的样式效果,给用户带来更好的展示体验. @font-face并不是CSS3的新特性,早在98年就被写入CSS2的规范当中,目前在IE6都可支持. 2.语法 @font-face { font-family: <FontName>; //自定义的字体名称 src: <source> [<format>][,<source> [<format>]]

iOS 从xib中加载自定义视图

想当初在学校主攻的是.NET,来到公司后,立马变成java开发,之后又跳到iOS开发,IT人这样真的好么~~  天有不测风云,云还有变幻莫测哎,废话Over,let's go~ 新学iOS开发不久,一直在想一个问题,IB可以图形化设计界面,为毛不直接拿设计好的界面直接复用呢? 百度了很多,发现大部分都是依赖Controller实现,要去设置File Owner,妹的,哥哥只是想复用一个简单的view好么,要你妹的控制器啊,于是接着搜,结果没有神马大的结果,主要是自己懒着动手去实践,今天决定自己去

自定义res/anim加载类,加载自定义Interpolator

上一篇文章 原文翻译 Android_Develop_API Guides_Animation Resources(动画资源) 介绍了Android中的动画资源,里面有一个章节是讲如何自定义插值器(Custom interpolators)的. 但是当前Android只为我们提供了自定义基于现有插值器的部分定制,只能修改当前要被修改的插值器所支持的属性. 例如: 文件位置:res/anim/my_overshoot_interpolator.xml: <?xml version="1.0&