精简加载自定义字体

来源:互联网 发布:剑网三优化版客户端 编辑:程序博客网 时间:2024/05/22 04:49

效果图:

核心源码:

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

使用注意事项:

 

0 0