iOS 来自 kCTFontManagerRegisteredFontsChangedNotification 通知的字体名称?

iOS font name from kCTFontManagerRegisteredFontsChangedNotification notification?

我正在通过发出 url 请求、从数据创建 CGFontRef 并使用 CTFontManagerRegisterGraphicsFont 注册来远程加载字体。如果我使用相同的数据并调用 CTFontManagerCreateFontDescriptorFromData 我可以获得字体名称。 如果我注册通知然后尝试获取名称,我就没有运气了。我返回 URL 不存在。如果我循环遍历 [UIFont familyNames],我发现它存在,问题是对我正在加载的内容有先验知识。这可以在不创建我自己的通知或替代方法来传递名称的情况下完成吗?

lldb: po note
__CFNotification 0xFFFFFFFFFFFF {name = CTFontManagerFontChangedNotification; userInfo = {
 CTFontManagerAvailableFontURLsAdded =     (
   "file://..."
 );
}}

- (void)noteHandler:(NSNotification *)note{
  NSDictionary *userInfo = [note userInfo];
  NSURL *fileURL = (NSURL *)([userInfo objectForKey:@"CTFontManagerAvailableFontURLsAdded"][0]);

  CFErrorRef error;
  Boolean reachable = CFURLResourceIsReachable((__bridge CFURLRef)(fileURL), &error);
  // error says file does not exist.
  CFArrayRef descriptors =  CTFontManagerCreateFontDescriptorsFromURL((__bridge CFURLRef)(fileURL));
  // null
}

我能够解决这个问题。栈溢出常说的是用CGDataProviderRefCGFontCreateWithDataProvider,然后用CTFontManagerRegisterGraphicsFont注册。问题是通知没有为您提供有效的 URL,您可以将其用于 CoreText api 中的 URL 调用。 加载字体的更好方法是先写入 tmp url,然后注册 url。然后通知传递 tmp url。 这是完整的例子..

NSURL *remoteLocation;
NSData *remoteContent;
...
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:[url.pathComponents componentsJoinedByString:@""]];
NSURL *fileURL = [NSURL fileURLWithPath:path];
NSError *error = nil;
if ([inData writeToURL:fileURL options:NSDataWritingAtomic error:&error]) {
    CFErrorRef cferror;
    if (CTFontManagerRegisterFontsForURL((__bridge CFURLRef)fileURL, kCTFontManagerScopeProcess, &cferror)) {
        // You take it from here..
    }
}

假设一切顺利,现在在通知中..

[theNoteCenter addObserver:self
                  selector:@selector(registeredFontChange:)
                      name:(NSString *)kCTFontManagerRegisteredFontsChangedNotification
                    object:nil];

- (void)registeredFontChange:(NSNotification *)note {
     NSDictionary *userInfo = [note userInfo];
     CFURLRef fileURL = (__bridge CFURLRef)([userInfo objectForKey:@"CTFontManagerAvailableFontURLsAdded"][0]);
     CFArrayRef allDescriptors = CTFontManagerCreateFontDescriptorsFromURL(fileURL);
     // I only happen to get a single descriptor
     CTFontDescriptorRef descriptor = CFArrayGetValueAtIndex(allDescriptors, 0);
     CFStringRef name = CTFontDescriptorCopyAttribute(descriptor, kCTFontNameAttribute);
     // Now you can use this font [UIFont fontWithName:... size:...]    
}