功能介绍
使用动态下载中文字体的 API 可以动态地向 iOS 系统中添加字体文件,这些字体文件都是下载到系统的目录中(目录是/private/var/mobile/Library/Assets/com_apple_MobileAsset_Font/),所以并不会造成应用体积的增加。并且,由于字体文件是 iOS 系统提供的,也免去了字体使用版权的问题。
查看字体名字 FontBook是系统应用程序
在官方文档中,苹果列出了提供动态下载和使用的中文字体文件列表。不过,由于下载的时候需要使用的名字是PostScript名称,所以如果你真正要动态下载相应的字体的话,还需要使用Mac内自带的应用字体册(Font Book)来获得相应字体的PostScript名称,下面是从字体册中获取“娃娃体-简 常规体”字体的PostScript名称的截图。
API 介绍
假如我们现在要下载娃娃体字体,它的 PostScript 名称为DFWaWaSC-W5,具体的步骤如下:
-
我们先判断该字体是否已经被下载下来了,代码如下:
- (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; } }
-
如果该字体已经下载过了,则可以直接使用。否则我们需要先准备下载字体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);
-
准备好上面的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; });