Created by shuimu 2020/05/25
提交到应用商店的允许在操作系统中提供系统范围内可用字体的应用程序。
要创建一个字体提供app,需要满足两个条件:
Fonts
相关的 entitlement
。在Capabilities
中找到并添加 Fonts
Fonts
包含两个选项:
Install Fonts:安装字体。
使app能够在系统范围内提供字体
Use Installed Fonts:使用已安装的字体。
默认情况下,应用程序无法访问用户安装的字体。应用程序需要选择这个功能,才能看到这些字体。
CoreText/CTFontManager.h
,引入了相关的APIs:
CTFontManagerRegisterFontURLs
使用指向字体文件的FontURLs
CTFontManagerRegisterFontDescriptors
通过使用字体描述符注册字体
CTFontManagerRegisterFontsWithAssetNames
注册存在于应用程序中的字体资源
CTFontManagerCopyRegisteredDescriptors
字体提供app用于访问已注册的字体
CTFontManagerRequestFonts
首先,应用程序应该提供一个有意义的UI,用户可以在其中浏览字体、安装和删除字体。
这是必要的,因为在iOS中,我们没有一个应用程序可以像在macOS中那样在操作系统中安装字体。
此外,应用程序应该响应系统字体更改通知。
原因是:用户能够在
设置
中删除字体,且应用应该注意到这一点并及时更新它的UI。
最后,如果你是一个字体提供程序,它计划提供一组很大的字体给用户,一个很大的字体库。
我们强烈建议您使用按需资源并将字体打包到资产目录中。
这是一种更有效的交付用户所需字体的方式,因为用户将只下载他们实际将要使用的字体。而不是下载一个巨大的字体库。
添加观察者,以便响应系统字体变更通知。
e.g.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fontsChangedNotification:) name:(__bridge NSString *)kCTFontManagerRegisteredFontsChangedNotification object:nil]; 复制代码
- (void)fontsChangedNotification:(id)noti { // 处理字体更新 ... [FontProvider updateRegisterdFonts]; dispatch_async(dispatch_get_main_queue(), ^{ // 更新相关UI ... }); } 复制代码
Register from fontURLs.
- (void)registerFontWithFontURL:(NSURL *)fontURL { NSURL *urls[] = {fontURL}; CFArrayRef fontURLs = CFArrayCreate(kCFAllocatorDefault, (void *)urls, (CFIndex)1, NULL); CTFontManagerRegisterFontURLs(fontURLs, kCTFontManagerScopePersistent, true, ^bool(CFArrayRef _Nonnull errors, bool done) { if (CFArrayGetCount(errors) > 0) { // regist failed CFErrorRef cfError = (CFErrorRef)CFArrayGetValueAtIndex(errors, 0); NSError *error = (__bridge_transfer NSError *)cfError; NSLog(@"Regist Font Failed: %@", [error localizedDescription]); return false; } return true; }); } 复制代码
Register from an asset catalog.
- (void)registerFontWithFontAssetName:(NSString *)fontAssetName { NSString *values[] = {fontAssetName}; CFArrayRef arrRef = CFArrayCreate(kCFAllocatorDefault, (void *)values, (CFIndex)1, NULL); CTFontManagerRegisterFontsWithAssetNames(arrRef, nil, kCTFontManagerScopePersistent, true, ^bool(CFArrayRef _Nonnull errors, bool done) { if (CFArrayGetCount(errors) > 0) { // regist failed CFErrorRef cfError = (CFErrorRef)CFArrayGetValueAtIndex(errors, 0); NSError *error = (__bridge_transfer NSError *)cfError; NSLog(@"Regist Font Failed: %@", [error localizedDescription]); return false; } return true; }); } 复制代码
注册方法中部分参数说明:
kCTFontManagerScopePersistent
以便其他app可以使用该字体CTFontManagerRequestFonts
被发现。一般选择true。Unregister by FontURLs.
- (void)unregisterFontWithFontURL:(NSURL *)fontURL { NSURL *urls[] = {fontURL}; CFArrayRef fontURLs = CFArrayCreate(kCFAllocatorDefault, (void *)urls, (CFIndex)1, NULL); CTFontManagerUnregisterFontURLs(fontURLs, kCTFontManagerScopePersistent, ^bool(CFArrayRef _Nonnull errors, bool done) { if (CFArrayGetCount(errors) > 0) { // regist failed CFErrorRef cfError = (CFErrorRef)CFArrayGetValueAtIndex(errors, 0); NSError *error = (__bridge_transfer NSError *)cfError; NSLog(@"Regist Font Failed: %@", [error localizedDescription]); return false; } return true; }); } 复制代码
Unregister by Font Descriptor.
- (void)unregisterFontWithFontDescriptor:(UIFontDescriptor *)fontDescriptor { CTFontDescriptorRef fontDescriptors[] = {(__bridge CTFontDescriptorRef)fontDescriptor}; CTFontManagerUnregisterFontDescriptors(CFArrayCreate(kCFAllocatorDefault, (void *)fontDescriptors, (CFIndex)1, NULL), kCTFontManagerScopePersistent, ^bool(CFArrayRef _Nonnull errors, bool done) { if (CFArrayGetCount(errors) > 0) { // regist failed CFErrorRef cfError = (CFErrorRef)CFArrayGetValueAtIndex(errors, 0); NSError *error = (__bridge_transfer NSError *)cfError; NSLog(@"Unregist Font Failed: %@", [error localizedDescription]); return false; } return true; }); } 复制代码
CTFontManagerCopyRegisteredFontDescriptors
仅可获取字体提供应用自己注册的字体
- (void)getRegisteredFonts { [FontProvider.registeredFonts removeAllObjects]; CFArrayRef registerdDescriptors = CTFontManagerCopyRegisteredFontDescriptors(kCTFontManagerScopePersistent, true); for (CFIndex i = 0; i < CFArrayGetCount(registerdDescriptors); i ++) { CTFontDescriptorRef fontDescriptorRef = CFArrayGetValueAtIndex(registerdDescriptors, i); UIFontDescriptor *fontDescriptor = (__bridge_transfer UIFontDescriptor *)fontDescriptorRef; // save registered fonts ... [FontProvider.registeredFonts addObject:fontDescriptor]; } } 复制代码