Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add a custom font to a Cocoapod?

I want to use a custom font within a Cocoapod, but I can't find anything on using a custom font within a static library. As there is no info.plist file, there is no where to tell the app what font to use.

Any ideas?

like image 791
Quentamia Avatar asked Oct 16 '12 16:10

Quentamia


People also ask

Where do I upload fonts?

Go to search in the start menu. Search for Fonts in settings. Click on the Fonts Folder to open the Font folder. Drag and Drop or Copy and Paste the unzipped fonts files into the Fonts folder to install.


2 Answers

There is a way of using a custom font without adding anything to the plist file.

    NSBundle *bundle = [NSBundle bundleForClass:[self class]];     NSURL *fontURL = [bundle URLForResource:<#fontName#> withExtension:@"otf"/*or TTF*/];     NSData *inData = [NSData dataWithContentsOfURL:fontURL];     CFErrorRef error;     CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)inData);     CGFontRef font = CGFontCreateWithDataProvider(provider);     if (!CTFontManagerRegisterGraphicsFont(font, &error)) {         CFStringRef errorDescription = CFErrorCopyDescription(error);         NSLog(@"Failed to load font: %@", errorDescription);         CFRelease(errorDescription);     }     CFSafeRelease(font);     CFSafeRelease(provider); 

You also need the CFSafeRelease function for this to work.

void CFSafeRelease(CFTypeRef cf) {     if (cf != NULL) {         CFRelease(cf);     } } 

Source: Loading iOS fonts dynamically.

Swift equivalent:

extension UIFont {     static func registerFont(bundle: Bundle, fontName: String, fontExtension: String) -> Bool {         guard let fontURL = bundle.url(forResource: fontName, withExtension: fontExtension) else {             fatalError("Couldn't find font \(fontName)")         }          guard let fontDataProvider = CGDataProvider(url: fontURL as CFURL) else {             fatalError("Couldn't load data from the font \(fontName)")         }          guard let font = CGFont(fontDataProvider) else {             fatalError("Couldn't create font from data")         }          var error: Unmanaged<CFError>?         let success = CTFontManagerRegisterGraphicsFont(font, &error)         guard success else {             print("Error registering font: maybe it was already registered.")             return false         }          return true     } } 
like image 74
Adam Avatar answered Sep 20 '22 02:09

Adam


If I understand correctly, you are trying to provide a font with your Cocoapod, and you intent the iOS apps which include the pod to be able to use your custom font.

This post_install hook seems to work:

Pod::Spec.new do |s|   # ...   s.resources = "Resources/*.otf"   # ...   s.post_install do |library_representation|     require 'rexml/document'      library = library_representation.library     proj_path = library.user_project_path     proj = Xcodeproj::Project.new(proj_path)     target = proj.targets.first # good guess for simple projects      info_plists = target.build_configurations.inject([]) do |memo, item|       memo << item.build_settings['INFOPLIST_FILE']     end.uniq     info_plists = info_plists.map { |plist| File.join(File.dirname(proj_path), plist) }      resources = library.file_accessors.collect(&:resources).flatten     fonts = resources.find_all { |file| File.extname(file) == '.otf' || File.extname(file) == '.ttf' }     fonts = fonts.map { |f| File.basename(f) }      info_plists.each do |plist|       doc = REXML::Document.new(File.open(plist))       main_dict = doc.elements["plist"].elements["dict"]       app_fonts = main_dict.get_elements("key[text()='UIAppFonts']").first       if app_fonts.nil?         elem = REXML::Element.new 'key'         elem.text = 'UIAppFonts'         main_dict.add_element(elem)         font_array = REXML::Element.new 'array'         main_dict.add_element(font_array)       else         font_array = app_fonts.next_element       end        fonts.each do |font|         if font_array.get_elements("string[text()='#{font}']").empty?           font_elem = REXML::Element.new 'string'           font_elem.text = font           font_array.add_element(font_elem)         end       end        doc.write(File.open(plist, 'wb'))     end   end 

The hook finds the user project, and in the first target (you probably can complete this solution by asking CocoaPods to give you the real target) it looks for its Info.plist file(s) (normally there is only one). Finally it looks for the UIAppFonts key of the file, creates it if not found, and fill the array with the font names if they are not already there.

like image 32
yonosoytu Avatar answered Sep 23 '22 02:09

yonosoytu