您的当前位置:首页正文

动态下载系统提供的中文字体

来源:要发发知识网

这个功能的实现,是自己看了唐巧大神的博客,学习的,目的是分享。

至于为什么要下载中文字体,有两个原因:
1、字体文件通常比较大,一个普通应用的大小10Mb,下载不划算
2、中文字体通常有版权

从iOS6开始,苹果支持动态下载中文字体到系统。

首先我们需要知道,中文字体的PostScript,查找方法如下:
spotlight -> font book 进去就可以看到中文字体,点击

WX20171026-143658@2x.png

然后就可以自己打开Xcode搞了,具体代码如下:

//
//  ViewController.m
//  动态下载系统提供的中文字体
//
//  Created by bh on 2017/10/25.
//  Copyright © 2017年 bh. All rights reserved.
//

#import "ViewController.h"
#import <CoreText/CoreText.h>

typedef void(^fontNameBlock)(UIFont *font);

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.label.text = @"这是一个字体测试的文本";
    
    [self dynamicSetFontName:@"Weibei-SC-Bold" fontSize:25 fontBlock:^(UIFont *font) {
        
        self.label.font = font;
    }];
}


- (void)dynamicSetFontName:(NSString *)fontName fontSize:(CGFloat)fontSize fontBlock:(fontNameBlock)fontBlock
{
    UIFont *aFont = [UIFont fontWithName:fontName size:fontSize];
    
    // 判断 该字体是否已经被下载 如果已经下载 直接返回
    if (aFont && ([aFont.fontName compare:fontName] == NSOrderedSame || [aFont.familyName compare:fontName] == NSOrderedSame)) {
        fontBlock(aFont);
        return;
    }
 
    // 下载字体
    // 用字体的PostScript名字创建一个Dictionary
    NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithObjectsAndKeys:fontName,kCTFontNameAttribute, nil];
    
    // 创建一个字体描述对象CTFontDescriptiorRef
    CTFontDescriptorRef desc = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef)attrs);
    
    // 将字体描述对象放到一个NSMutableArray中
    NSMutableArray *descs = [NSMutableArray arrayWithCapacity:0];
    [descs addObject:(__bridge id)desc];
    CFRelease(desc);
    
    __block BOOL errorDuringDownload = NO;
    
    CTFontDescriptorMatchFontDescriptorsWithProgressHandler((__bridge CFArrayRef)descs, NULL, ^bool(CTFontDescriptorMatchingState state, CFDictionaryRef  _Nonnull progressParameter) {
        
        double progressValue = [[(__bridge NSDictionary *)progressParameter objectForKey:(id)kCTFontDescriptorMatchingPercentage] doubleValue];
        
        if (state == kCTFontDescriptorMatchingDidBegin) {
            NSLog(@"字体已经匹配");
        }else if (state == kCTFontDescriptorMatchingDidFinish) {
            if (!errorDuringDownload) {
                NSLog(@"字体%@ 下载完成",fontName);
                dispatch_async(dispatch_get_main_queue(), ^{
                    UIFont *newFont = [UIFont fontWithName:fontName size:fontSize];
                    fontBlock(newFont);
                });
            }
        }else if (state == kCTFontDescriptorMatchingWillBeginDownloading) {
            NSLog(@"字体开始下载");
        }else if (state == kCTFontDescriptorMatchingDidFinishDownloading) {
            NSLog(@"字体下载完成");
        }else if (state == kCTFontDescriptorMatchingDownloading) {
            NSLog(@"progress %.0f%%",progressValue);
        }else if (state == kCTFontDescriptorMatchingDidFailWithError) {
            NSError *error = [(__bridge NSDictionary *)progressParameter objectForKey:(id)kCTFontDescriptorMatchingError];
            
            if (error != nil) {
                NSLog(@"%@",[error description]);
            }else {
                NSLog(@"ERROR MESSAGE IS NOT AVAILABLE!");
            }
            
            errorDuringDownload = YES;
            
        }
        
        return (BOOL)YES;
    });
}

- (void)dealloc
{
    NSLog(@"%s",__func__);
}

@end

我也是根据大神的思路,看着实现了一把,再加上自己可能用到的方式,希望可以互相学习和交流