I'm loading font's remotely by making a url request, creating a CGFontRef
from data, and registering it with CTFontManagerRegisterGraphicsFont
. If I use the same data and call CTFontManagerCreateFontDescriptorFromData
I can get the font name.
If I register for the notification and then try to get the name, I'm not having any luck. I get back that the URL doesn't exist. If I loop through the [UIFont familyNames]
I see that it exists, the problem is having prior knowledge to what I'm loading. Can this be done without creating my own notifications or alternative to pass the name around?
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
}
I was able to fix this. It's common on stack overflow to talk about using CGDataProviderRef
, CGFontCreateWithDataProvider
and then registering with CTFontManagerRegisterGraphicsFont
. The problem is that the notification doesn't give you a valid URL that you can use for the URL calls within CoreText api's.
The better way to load the font is by writing to a tmp url first, then registering that url. Then the notification passes the tmp url along.
Here's the full example..
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..
}
}
Now in the notification assuming all goes well..
[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:...]
}