30

Cocoapod内でカスタムフォントを使用したいのですが、静的ライブラリ内でカスタムフォントを使用しても何も見つかりません。info.plistファイルがないため、使用するフォントをアプリに指示する場所がありません。

何か案は?

4

5 に答える 5

16

plist ファイルに何も追加せずにカスタム フォントを使用する方法があります。

    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これを機能させるには、関数も必要です。

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

出典: iOS フォントを動的にロードする.

スウィフトの同等物:

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
    }
}
于 2016-04-26T16:48:21.180 に答える
12

私の理解が正しければ、あなたは Cocoapod にフォントを提供しようとしており、ポッドを含む 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ファイルを探します (通常は 1 つだけです)。最後にUIAppFonts、ファイルのキーを探し、見つからない場合は作成し、フォント名がまだ存在しない場合は配列を埋めます。

于 2013-06-08T01:51:50.990 に答える