如何将自定义字体添加到Cocoapod?

时间:2012-10-16 16:43:12

标签: iphone ios uifont cocoapods

我想在Cocoapod中使用自定义字体,但在静态库中使用自定义字体时找不到任何内容。由于没有info.plist文件,因此无法告诉应用程序使用什么字体。

有什么想法吗?

5 个答案:

答案 0 :(得分:10)

如果我理解正确,您正在尝试使用Cocoapod提供字体,并且您希望包含该pod的iOS应用程序能够使用您的自定义字体。

post_install挂钩似乎有效:

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

钩子找到用户项目,并且在第一个目标中(您可能通过要求CocoaPods为您提供真正的目标来完成此解决方案)它会查找其Info.plist文件(通常只有一)。最后,它查找文件的UIAppFonts键,如果找不到则创建它,并在数组中填入字体名称(如果它们不在那里)。

答案 1 :(得分:8)

对于那些在2018年以上发现这一点的人,我通过这两个步骤获得了自定义字体界面构建器支持(XCode 9):

  1. 将您的字体添加到资源包

    s.resource_bundles = {
      'PodName' => ['PodName/**/*.{ttf}']
    }
    
  2. 使用上面的Adam回答

    在运行时加载字体
    #import <CoreText/CoreText.h>
    
    void CFSafeRelease(CFTypeRef cf) { // redefine this
      if (cf != NULL) {
        CFRelease(cf);
      }
    }
    
    
    + (void) loadFonts {
      NSBundle *frameworkBundle = [NSBundle bundleForClass:self.classForCoder];
      NSURL *bundleURL = [[frameworkBundle resourceURL] URLByAppendingPathComponent:@"PodName.bundle"];
      NSBundle *bundle = [NSBundle bundleWithURL:bundleURL];
    
      NSURL *fontURL = [bundle URLForResource:@"HindMadurai-SemiBold" withExtension:@"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);
    }
    

答案 2 :(得分:6)

有一种方法可以使用自定义字体而不向plist文件添加任何内容。

var str = "abc abc ab a";
var i = -1;
var result = [];

while (true) {
    i = str.indexOf("abc", i + 1);
    if (i == -1) break;
    result.push(i);
}

document.write(result);

您还需要 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); 功能才能实现此功能。

CFSafeRelease

来源:Loading iOS fonts dynamically

Swift等价物:

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

答案 3 :(得分:1)

好吧,idk如果可以回答的话,但是您也可以 查找需要字体的cocoapod,如下所示: https://github.com/parakeety/GoogleFontsiOS

库包含许多字体,我需要Chivo,因此我添加了pod'GoogleFontsiOS / Chivo' 并用它代替自己编写字体加载代码。

答案 4 :(得分:0)

迅速实施5

我能够通过在Cocoapod中创建以下类,然后从主应用程序CustomFonts.loadAll()中调用AppDelegate.swift来解决此问题。之后,我可以在我的应用中使用这样的字体:

let myFont = CustomFonts.Style.regular.font

请注意,Style枚举不是必需的,只是分离关注点的便捷方法。您也可以致电:

let myFont = UIFont(name: "SourceSansPro-SemiBold", size: 14)

import CoreText

public class CustomFonts: NSObject {

  public enum Style: CaseIterable {
    case mono
    case regular
    case semibold
    public var value: String {
      switch self {
      case .mono: return "SourceCodePro-Medium"
      case .regular: return "SourceSansPro-Regular"
      case .semibold: return "SourceSansPro-SemiBold"
      }
    }
    public var font: UIFont {
      return UIFont(name: self.value, size: 14) ?? UIFont.init()
    }
  }

  // Lazy var instead of method so it's only ever called once per app session.
  public static var loadFonts: () -> Void = {
    let fontNames = Style.allCases.map { $0.value }
    for fontName in fontNames {
      loadFont(withName: fontName)
    }
    return {}
  }()

  private static func loadFont(withName fontName: String) {
    guard
      let bundleURL = Bundle(for: self).url(forResource: "[CococpodName]", withExtension: "bundle"),
      let bundle = Bundle(url: bundleURL),
      let fontURL = bundle.url(forResource: fontName, withExtension: "ttf"),
      let fontData = try? Data(contentsOf: fontURL) as CFData,
      let provider = CGDataProvider(data: fontData),
      let font = CGFont(provider) else {
        return
    }
    CTFontManagerRegisterGraphicsFont(font, nil)
  }

}