MScottWaller MScottWaller - 1 year ago 103
Objective-C Question

How can I download and install fonts dynamically to iOS app

A client would like to dynamically add fonts to an iOS app by downloading them with an API call.

Is this possible? All the resources I've dredged up show how to manually drag the .ttf file to Xcode and add it to the plist. Is it possible to download a font and use it on the fly client side, programmatically?

Thanks.

Answer Source

Okay, so here is how I did it. First where needed do this:

#import <CoreText/CoreText.h>

Then make your NSURLSession call. My client uploaded a font to Amazon's S3. So do this where needed:

// 1
NSString *dataUrl = @"http://client.com.s3.amazonaws.com/font/your_font_name.ttf";
NSURL *url = [NSURL URLWithString:dataUrl];

// 2
NSURLSessionDataTask *downloadTask = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // 4: Handle response here
    if (error == nil) {
        NSLog(@"no error!");
        if (data != nil) {
            NSLog(@"There is data!");
            [self loadFont:data];
        }
    } else {
        NSLog(@"%@", error.localizedDescription);
    }
}];

// 3
[downloadTask resume];

My loadFont data is here:

- (void)loadFont:(NSData *)data
{
    NSData *inData = data;
    CFErrorRef error;
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
    CGFontRef font = CGFontCreateWithDataProvider(provider);
    if(!CTFontManagerRegisterGraphicsFont(font, &error)){
        CFStringRef errorDescription = CFErrorCopyDescription(error);
        NSLog(@"Failed to load font: %@", errorDescription);
        CFRelease(errorDescription);
    }
    CFRelease(font);
    CFRelease(provider);

    [self fontTest];
}

Then that fontTest at the end is just to make sure the font is actually there, and in my case, it was! And also, it showed up when the app ran where needed.

- (void)fontTest
{
    NSArray *fontFamilies = [UIFont familyNames];
    for (int i = 0; i < [fontFamilies count]; i++) {
        NSString *fontFamily = [fontFamilies objectAtIndex:i];
        NSArray *fontNames = [UIFont fontNamesForFamilyName:[fontFamilies objectAtIndex:i]];
        NSLog (@"%@: %@", fontFamily, fontNames);
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download