I added custom font to a framework. I followed all the steps, but it doesn\'t work.
I am able to set the font in Interface Builder, but when I build the project it d
I thought I'd share my answer as well. My project is set up like so:
Main iOS App (Swift)
Dynamic Framework (Obj-C)
Fonts.bundle (a bundle with all the fonts inside)
UIFont categories
NSBundle categories
Other framework classes
App Classes (ViewControllers, Models, CoreData, etc...)
My goal was to be able to have the main app call a single method on the dynamic framework to load fonts without the need for altering the Info.plist or adding the font files/bundle to the main target.
@import CoreText;
@implementation NSBundle (Fonts)
+ (NSBundle *)fontsBundle {
// The only way I could find to do this is to hard code the sub-path. Using pathForResource doesn't seem to find Fonts.bundle, nor its contents\
// This way the host app doesn't need to copy Fonts.bundle
NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Frameworks/.framework/Fonts.bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:path];
if (bundle == nil) {
NSLog(@"Warning: Fonts.bundle could not be loaded. Have you included it in your target?");
}
return bundle;
}
- (BOOL)loadFonts {
NSArray *names = @[
@"GothamRnd-Bold",
@"GothamRnd-BoldItal",
@"GothamRnd-Book",
@"GothamRnd-BookItal",
@"GothamRnd-Light",
@"GothamRnd-LightItal",
@"GothamRnd-MedItal",
@"GothamRnd-Medium",
];
__block NSInteger failCounter = 0;
[names enumerateObjectsUsingBlock:^(id _Nonnull name, NSUInteger idx, BOOL *_Nonnull stop) {
NSString *fontPath = [self pathForResource:name ofType:@"otf"];
NSData *inData = [NSData dataWithContentsOfFile:fontPath];
CFErrorRef error;
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)inData);
CGFontRef font = CGFontCreateWithDataProvider(provider);
if (!CTFontManagerRegisterGraphicsFont(font, &error)) {
if (error) {
NSLog(@"Failed to load font at path: %@", fontPath);
failCounter++;
}
CFStringRef errorDescription = CFErrorCopyDescription(error);
NSLog(@"Failed to load font: %@", errorDescription);
CFRelease(errorDescription);
}
CFRelease(font);
CFRelease(provider);
}];
return failCounter == 0;
}
@end
The only bummer in this code is you have to hard code the path to the Fonts.bundle. I couldn't get any combination of NSBundle methods to locate the Fonts.bundle file automatically. For instance no methods like this would return a path:
NSString *pathToBundle = [[NSBundle mainBundle] pathForResource:@"Fonts" ofType:@"bundle"];
NSString *pathToFont = [[NSBundle mainBundle] pathForResource:@"MyFont" ofType:@"ttf"];
Aside from the hard coding (which will never change), this is working for me well enough though. I can now skin all of my client apps easily.