Cocoapod内でカスタムフォントを使用したいのですが、静的ライブラリ内でカスタムフォントを使用しても何も見つかりません。info.plistファイルがないため、使用するフォントをアプリに指示する場所がありません。
何か案は?
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
}
}
私の理解が正しければ、あなたは 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
、ファイルのキーを探し、見つからない場合は作成し、フォント名がまだ存在しない場合は配列を埋めます。