iOS 动态下载系统提供的多种中文字体
一、功能简介
1、前言
为了实现更好的字体效果,有些应用在自己的应用资源包中加入了字体文件。但自己打包字体文件比较麻烦,原因在于:
1.字体文件通常比较大,10~20M
是常见的字体库大小。如果只是很少量的按钮字体需要设置,可以用一些工具把使用的汉字字体编码从字体库中抽取出来,以节省体积。但是如果是一些变化的内容需要自定义的字体,那么就只能打包整个字体库了。
2.中文字体都是有版权的,在应用中加入特殊中文字体还需要处理相应的版权问题。
从iOS6
开始,苹果开始支持动态下载官方提供的中文字体到系统中。使用苹果官方的中文字体,即可以避免版权问题,又可以节省应用体积。
2、功能介绍
使用动态下载中文字体的API可以动态的向iOS系统中添加字体文件,这些字体文件都是下载带到系统的目录中,所以并不会造成应用体积的增加。虽然第一次下载相关的中文字体需要一些网络开销和下载时间,但是这些字体文件下载完后可以在所有应用间共享,所以大部分应用都不需提示用户下载字体,因为很可能这些字体在之前被其他应用下载过了。
3、字体列表
在官方文档中,苹果列出了提供动态下载和使用的中文字体文件列表。不过,由于下载的时候需要使用的名字是PostScript
名称,所以如果你真正要动态下载相应的字体的话,还需要使用Mac
内自带的应用字体册Font Book
来获得相应字体的PostScrip
t名称。下面是从字体册中获取“娃娃体-简 常规体”
字体的PostScript
名称的截图。
二、使用教程
1、相关API介绍
苹果提供了动态下载代码的Demo
工程。将此Demo
工程下载下来,可以学习相关API
的使用。下面对该工程中相关API
做简单的介绍。
假如我们现在要下载“娃娃体”,他的PostScript
名称为“DFWaWaSC-W5”
。具体操作步骤如下:
1、我们先判断该字体是否已经被下载下来,示例代码:
//判断该字体是否已经被下载下来了
- (BOOL)isFontDownloaded:(NSString *)fontName {
UIFont *aFont = [UIFont fontWithName:fontName size:12.0];
if (aFont && ([aFont.fontName compare:fontName] == NSOrderedSame || [aFont.familyName compare:fontName] == NSOrderedSame)) {
return YES;
}else{
return NO;
}
}
2、如果该字体已经下载过了,则可以直接使用。否则我们需要先准备下载字体API
需要的一些参数,示例代码:
//用字体的PostScript名字创建一个 dictionary
NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithObjectsAndKeys:fontName,kCTFontNameAttribute, nil];
//创建一个字体描述对象 CTFontDescriptorRef
CTFontDescriptorRef desc = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef)attrs);
//将字体描述对象放到一个NSMutableArray中
NSMutableArray *descs = [NSMutableArray arrayWithCapacity:0];
[descs addObject:(__bridge id _Nonnull)desc];
CFRelease(desc);
3、准备好上面的descs
变量后,就可以进行字体的下载了,示例代码:
__block BOOL errorDuringDownload = NO;
//下载字体
CTFontDescriptorMatchFontDescriptorsWithProgressHandler((__bridge CFArrayRef)descs , NULL, ^bool(CTFontDescriptorMatchingState state, CFDictionaryRef _Nonnull progressParameter) {
double progressValue = [[(__bridge NSDictionary *)progressParameter objectForKey:(id)kCTFontDescriptorMatchingPercentage] doubleValue];
switch (state) {
case kCTFontDescriptorMatchingDidBegin:
//字体已经匹配
break;
case kCTFontDescriptorMatchingWillBeginDownloading:
//字体开始下载
break;
case kCTFontDescriptorMatchingDownloading:
NSLog(@" 下载进度 %.0f",progressValue);
break;
case kCTFontDescriptorMatchingDidFinishDownloading:
//字体下载完成
break;
case kCTFontDescriptorMatchingDidFinish:
{
//字体已经下载完成
if (!errorDuringDownload) {
NSLog(@"字体%@ 已经下载完成",fontName);
dispatch_async( dispatch_get_main_queue(), ^ {
// 可以在这里修改 UI 控件的字体
_label.font = [UIFont fontWithName:_postName size:14];
return ;
});
}
}
break;
case kCTFontDescriptorMatchingDidFailWithError:
//下载错误
{
NSError *error = [(__bridge NSDictionary *)progressParameter objectForKey:(id)kCTFontDescriptorMatchingError];
if (error != nil) {
_errorMessage = [error description];
} else {
_errorMessage = @"ERROR MESSAGE IS NOT AVAILABLE!";
}
// 设置标志
errorDuringDownload = YES;
NSLog(@" 下载错误: %@", _errorMessage);
}
break;
default:
break;
}
return YES;
});
通常需要在下载完字体后开始使用字体,一般是将相应的代码放到 kCTFontDescriptorMatchingDidFinish
条件中,可以像苹果官方Demo
那样,用GCD
来修改UI
逻辑,也可以发Notification
来通知相应的Controller
。
参考:https://blog.csdn.net/liu_wentao/article/details/72900360
本文Demo下载地址