zoukankan      html  css  js  c++  java
  • 精简加载自定义字体

    精简加载自定义字体

    效果图:

    核心源码:

    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

    使用注意事项:

  • 相关阅读:
    js4——字符转化
    js3——表格下拉
    笔记展现
    js2——定时跳转
    js学习——1
    明明在/etc/my.cnf 配置了mysql.sock,为什么会在/var/lib/mysql/mysql.sock 里边寻找
    RBAC用户权限管理数据库设计
    mysql 字节问题,中文和数字
    PHP闭包
    一致性哈希算法原理
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3984164.html
Copyright © 2011-2022 走看看