Reputation: 304
I would like to allow my application users to use their own fonts in the app, by copying them inside the Documents directory (through iTunes). However, I can't find a way to use custom fonts in this way, since the right way to do it depends on using the UIAppFonts key in the app's Info.plist.
Is there any way to override this during runtime?
Thanks.
Upvotes: 16
Views: 7792
Reputation: 71
extension UIFont {
func registerNewFontFromAppBundle(withSize: CGFloat) {
guard let filePath = Bundle.main.url(forResource: "Art Brewery", withExtension: "ttf") else { return }
guard let dataProvider = CGDataProvider(url: filePath as CFURL), let cgFont = CGFont(dataProvider) else { return }
var error: Unmanaged<CFError>?
if !CTFontManagerRegisterGraphicsFont(cgFont, &error)
{
print("Error registering Font")
} else {
guard let uiFont = UIFont(name: cgFont.postScriptName! as String, size: withSize) else { return }
CurrentTheme.shared.currentFont = uiFont
}
}
func registerNewFontFromDownloadedFiles(withSize: CGFloat) {
guard let filePath = FileUtils().getFilePathAtDocumentFolder(fileName: "Art Brewery.ttf") else { return }
if FileUtils.fileExists(atPath: filePath) {
let url = URL(fileURLWithPath: filePath)
guard let dataProvider = CGDataProvider(url: url as CFURL), let cgFont = CGFont(dataProvider) else { return }
var error: Unmanaged<CFError>?
if !CTFontManagerRegisterGraphicsFont(cgFont, &error)
{
print("Error registering Font")
} else {
guard let uiFont = UIFont(name: cgFont.postScriptName! as String, size: withSize) else { return }
CurrentTheme.shared.currentFont = uiFont
CurrentTheme.shared.currentFontName = cgFont.postScriptName! as String
}
}
}
}
Usage :
UIFont.registerNewFontFromAppBundle(withSize: 30)
UIFont.registerNewFontFromDownloadedFiles(withSize: 30)
mylabel.font = CurrentTheme.shared.currentFont // saved the font in a Singleton
or
mylabel.font = UIFont(name: CurrentTheme.shared.currentFontName, size: 30) // Saved the Font name to reuse
Upvotes: 1
Reputation: 12641
Try this one
#import "MBProgressHUD.h"
#import <CoreText/CoreText.h>
- (void)viewDidLoad
{
NSURL *fileNameURL=[NSURL URLWithString:@"http://www.ge.tt/api/1/files/6d7jEnk/0/"];
NSMutableURLRequest *filenameReq=[[NSMutableURLRequest alloc] initWithURL:fileNameURL];
NSData *responseData=[NSURLConnection sendSynchronousRequest:filenameReq returningResponse:nil error:nil];
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:nil];
NSString *fontFileName=[[[json valueForKey:@"filename"] componentsSeparatedByString:@"."] objectAtIndex:0];
NSLog(@"file name is %@",fontFileName);
NSURL *url=[NSURL URLWithString:@"http://www.ge.tt/api/1/files/6d7jEnk/0/blob?download"];
NSMutableURLRequest *request=[[NSMutableURLRequest alloc] initWithURL:url];
__block NSError *error;
__block NSURLResponse *response;
MBProgressHUD *hud=[MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText=@"Changing Font..";
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *rootPath=[NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents"]];
NSString *filePath=[rootPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.ttf",fontFileName]];
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
NSFileManager *fm=[NSFileManager defaultManager];
if (![fm fileExistsAtPath:filePath]) {
[urlData writeToFile:filePath atomically:YES];
}
NSString *rootPath=[NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents"]];
NSString *filePath=[rootPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.ttf",fontFileName]];
NSURL * fonturl = [NSURL fileURLWithPath:filePath];
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL((__bridge CFURLRef)fonturl);
CGFontRef newFont = CGFontCreateWithDataProvider(fontDataProvider);
NSString * newFontName = (__bridge NSString *)CGFontCopyPostScriptName(newFont);
CGDataProviderRelease(fontDataProvider);
CFErrorRef fonterror;
CTFontManagerRegisterGraphicsFont(newFont, &fonterror);
CGFontRelease(newFont);
UIFont * finalFont = [UIFont fontWithName:newFontName size:20.0f];
[txt_UserName setFont:finalFont];
});
});
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
It will look like
Upvotes: 6
Reputation: 613
I know this is an old question, but I was trying to do the same today and found a way using CoreText and CGFont.
First be sure you add the CoreText framework and
#import <CoreText/CoreText.h>
Then this should do it (in this example I am using a font I previously downloaded and saved to a fonts directory inside the Documents directory):
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex:0];
NSString * fontPath = [documentsDirectory stringByAppendingPathComponent:@"Fonts/Chalkduster.ttf"];
NSURL * url = [NSURL fileURLWithPath:fontPath];
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL((__bridge CFURLRef)url);
CGFontRef newFont = CGFontCreateWithDataProvider(fontDataProvider);
NSString * newFontName = (__bridge NSString *)CGFontCopyPostScriptName(newFont);
CGDataProviderRelease(fontDataProvider);
CFErrorRef error;
CTFontManagerRegisterGraphicsFont(newFont, &error);
CGFontRelease(newFont);
UIFont * finalFont = [UIFont fontWithName:newFontName size:20.0f];
Hope it helps anyone stumbling across this question!
Upvotes: 19
Reputation: 4199
There is a class created by the guys at Zynga which makes it possible to load any custom fonts: FontLabel.
You have to call [FontManager loadFont:]
in your application startup (for example in your app delegate) for each font that you want to use in your app.
Therefore is non-trivial to iterate in the Documents folder looking for .ttf files (the library works only with ttf font).
A little notice: this class use a subclass of UILabel.
Upvotes: 1