我向苹果的DTS(开发技术支持)提交了一个工单,他们回复说:
“您需要跟踪使用CTFontManagerRegisterGraphicsFont注册的字体。 CTFontManagerRegisterGraphicsFont返回的错误代码kCTFontManagerErrorAlreadyRegistered将告诉您是否已经注册了字体。使用字体描述符匹配来发现安装的字体可能不是一个好方法,因为系统可能选择对缺失字体执行字体替换。使用CTFontManagerRegisterGraphicsFont安装字体只是使其可供应用程序使用。它不是一种查询服务,用于发现已安装的字体。如果这对您的偏好不足够,请考虑提出功能请求,要求您想要接收的功能。”
因此,基本上我们需要自己跟踪我们注册的字体。
我最终使用的解决方法/变通方法是:
目前,我的应用程序允许用户使用“复制到MYAPP”按钮在字体文件上添加字体。这个解决方案也适用于我从服务器下载的字体文件。
为了使我的应用程序在ttf和otf文件的操作表中列出,在我的应用程序的info.plist中,我添加了一个新的文档类型:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFiles</key>
<array/>
<key>CFBundleTypeName</key>
<string>Font</string>
<key>LSItemContentTypes</key>
<array>
<string>public.opentype-font</string>
<string>public.truetype-ttf-font</string>
</array>
</dict>
</array>
这使得我的应用程序可以在任何字体文件上显示在"操作表"中。因此,用户可以将字体文件放在Dropbox、Google Drive或任何其他文件共享应用程序中。然后,他们可以从那里将字体导入到我的应用程序中。导入后,我需要将字体文件从临时的"tmp inbox"文件夹移动到我的应用程序的"Documents fonts"目录中。"fonts"目录保存所有自定义字体。之后,我注册这个自定义字体,并将其名称添加到"self.arrayOfFonts"数组中。这是包含所有我的字体列表的数组。
此外,似乎"CTFontManagerRegisterGraphicsFont"仅适用于会话。因此,当应用程序从应用切换器中关闭并重新启动时,该字体不再注册。因此,在每次启动后,我都会浏览我的"documents fonts"文件夹,重新注册所有字体,并将其名称添加到"self.arrayOfFonts"数组中。
为了使其可行,请查看我的应用代码:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
if ([url isFileURL])
{
NSLog(@"handleOpenURL: %@, extension: %@",url.absoluteString,url.pathExtension);
[self moveFontFrom:url];
return YES;
}
else
{
return NO;
}
}
-(void)moveFontFrom:(NSURL*)fromurl{
NSString *stringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0] stringByAppendingPathComponent:@"fonts"];
NSError *error1 = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:stringPath]){
[[NSFileManager defaultManager] createDirectoryAtPath:stringPath withIntermediateDirectories:NO attributes:nil error:&error1];
}
NSLog(@"error1: %@", error1.debugDescription);
NSURL *tourl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@",stringPath,[[fromurl absoluteString] lastPathComponent]] isDirectory:NO];
NSLog(@"Trying to move from:\n\n%@\n\nto:\n\n%@\n\n", fromurl.absoluteString,tourl.absoluteString);
NSError* error2;
if ([[NSFileManager defaultManager] fileExistsAtPath:tourl.path]){
[[NSFileManager defaultManager] removeItemAtPath:tourl.path error:&error2];
NSLog(@"Deleting old existing file at %@ error2: %@", tourl.path,error2.debugDescription);
}
NSError* error3;
[[NSFileManager defaultManager] moveItemAtURL:fromurl toURL:tourl error:&error3];
NSLog(@"error3: %@", error3.debugDescription);
if (!error3) {
NSString *fontName = [self registerFont:tourl checkIfNotify:YES];
if (fontName) {
if (![self.arrayOfFonts containsObject:fontName]) {
[self.arrayOfFonts addObject:fontName];
[self.arrayOfFonts sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
[[NSNotificationCenter defaultCenter] postNotificationName:@"refreshFont" object:nil userInfo:@{@"font":fontName}];
}
}
}
}
-(void)startupLoadFontsInDocuments{
self.arrayOfFonts = [NSMutableArray new];
NSString *location = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0] stringByAppendingPathComponent:@"fonts"];
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:location error:NULL];
for (NSInteger count = 0; count < [directoryContent count]; count++)
{
NSLog(@"File %ld: %@/%@", (count + 1), location,[directoryContent objectAtIndex:count]);
NSString *fontName = [self registerFont:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@",location,[directoryContent objectAtIndex:count]] isDirectory:NO] checkIfNotify:NO];
if (fontName) {
if (![self.arrayOfFonts containsObject:fontName]) {
[self.arrayOfFonts addObject:fontName];
}
}
}
[self.arrayOfFonts sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}
-(NSString*)registerFont:(NSURL *)url checkIfNotify:(BOOL)checkIfNotify{
NSData *inData = [NSData dataWithContentsOfURL:url];
CFErrorRef registererror;
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)inData);
CGFontRef fontRef = CGFontCreateWithDataProvider(provider);
NSString *fontName = (__bridge NSString *)CGFontCopyPostScriptName(fontRef);
BOOL registerFontStatus = CTFontManagerRegisterGraphicsFont(fontRef, ®istererror);
if (!registerFontStatus) {
CFStringRef errorDescription = CFErrorCopyDescription(registererror);
NSError *registererr = (__bridge NSError*)registererror;
if ([registererr code]==kCTFontManagerErrorAlreadyRegistered) {
NSLog(@"Font is already registered!");
}
NSLog(@"Failed to load font: %@", registererror);
CFRelease(errorDescription);
if (checkIfNotify) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Already added" message:@"That font is already added to the app. Please select it from the fonts list." preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
}]];
[[self.window rootViewController] presentViewController:alert animated:YES completion:nil];
}
} else {
CFStringRef fontNameRef = CGFontCopyPostScriptName(fontRef);
fontName = (__bridge NSString*)fontNameRef;
CFRelease(fontNameRef);
NSLog(@"fontName: %@",fontName);
}
CFRelease(fontRef);
CFRelease(provider);
return fontName;
}
注意:如您所见,我已将CTFontManagerUnregisterGraphicsFont
注释掉。使用CTFontManagerUnregisterGraphicsFont
注销字体似乎对我无效,因为它会出现错误,提示该字体正在使用中,因此无法注销。因此,当我需要删除字体时,我只需从self.arrayOfFonts
数组和我的documents/fonts
文件夹中删除即可。
CTFontManagerCopyAvailablePostScriptNames
吗? - rob mayoffCTFontManagerCopyAvailablePostScriptNames
和CTFontManagerCopyAvailableFontFamilyNames
方法,但两者都只打印出iOS上已有字体的名称,而不是我通过CTFontManagerRegisterGraphicsFont
注册的字体。 - sudoExclaimationExclaimation