リソースをパッケージ化するためのバンドルを使用してiosframeworkを作成しています(ペン先、画像、フォント)とバンドルにカスタムフォントを埋め込もうとしていますが、フレームワークからロードできません。出来ますか ?
1)これでフォントファイルをローカライズできます:objc NSString *fontPath = [[NSBundle frameworkBundle] pathForResource:@"MyCustomFont" ofType:@"ttf"];
2)しかし、フォントリストに表示されません:objc NSArray * array = [UIFont familyNames];
「アプリケーションによって提供されるフォント」とともにバンドルのplistにフォント名を含めましたが、成功しませんでした。アプリ情報plistでも試しましたが、フレームワークリソースに含めましたが成功しませんでした。
バンドルからペン先と画像を(バンドルの名前を前に付けることで)ロードできますが、フォントはロードできません。何か考えはありますか?
編集:次の投稿を見ました: iPhoneアプリケーションにカスタムフォントを埋め込むことはできますか? 、しかし問題はただです「iPhoneアプリケーションにカスタムフォントを埋め込むことはできますか?」 「外部フレームワーク/バンドルにカスタムフォントを埋め込むことはできますか?」ではありません。また、興味深い動的ロードへの参照も作成しますが、フレームワークに使用できないソリューションであるプライベートAPIを使用しています。
ありがとう
これは、Info.plistにフォントを入れずに動的にフォントをロードできる新しい方法です: http://www.marco.org/2012/12/21/ios-dynamic-font-loading
これが、「DavidM」が提供するソリューションに基づいてfmkに実装した方法です。このソリューションでは、plistのフォントへの参照を追加する必要はありません。
1)フォントをロードするクラス
- (void) loadMyCustomFont{
NSString *fontPath = [[NSBundle frameworkBundle] pathForResource:@"MyFontFileNameWithoutExtension" ofType:@"ttf"];
NSData *inData = [NSData dataWithContentsOfFile:fontPath];
CFErrorRef error;
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)inData);
CGFontRef font = CGFontCreateWithDataProvider(provider);
if (! CTFontManagerRegisterGraphicsFont(font, &error)) {
CFStringRef errorDescription = CFErrorCopyDescription(error);
NSLog(@"Failed to load font: %@", errorDescription);
CFRelease(errorDescription);
}
CFRelease(font);
CFRelease(provider);
}
2)バンドルにアクセスするためのNSBundleのカテゴリ
+ (NSBundle *)frameworkBundle {
static NSBundle* frameworkBundle = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
NSString* mainBundlePath = [[NSBundle mainBundle] resourcePath];
NSString* frameworkBundlePath = [mainBundlePath stringByAppendingPathComponent:@"MyBundleName.bundle"];
frameworkBundle = [NSBundle bundleWithPath:frameworkBundlePath];
});
return frameworkBundle;
}
注:CoreTextをプロジェクトに統合する必要があります
スウィフト3:
まず、パスコンポーネントを追加してメインからフレームワークバンドルにアクセスしないでください...識別子からインスタンス化します。次のようなフォントURLを取得できます。
static func fontsURLs() -> [URL] {
let bundle = Bundle(identifier: "com.company.project.framework")!
let fileNames = ["Roboto-Bold", "Roboto-Italic", "Roboto-Regular"]
return fileNames.map({ bundle.url(forResource: $0, withExtension: "ttf")! })
}
そして、フォントを登録するためのUIFont
拡張子があるのはいいことだと思います。
public extension UIFont {
public static func register(from url: URL) throws {
guard let fontDataProvider = CGDataProvider(url: url as CFURL) else {
throw SVError.internal("Could not create font data provider for \(url).")
}
let font = CGFont(fontDataProvider)
var error: Unmanaged<CFError>?
guard CTFontManagerRegisterGraphicsFont(font, &error) else {
throw error!.takeUnretainedValue()
}
}
}
今すぐ登録をお楽しみください:
do {
try fontsURLs().forEach({ try UIFont.register(from: $0) })
} catch {
print(error)
}
Swiftでは、以下のコードを使用します。
public class func loadMyCustomFont(name:String) -> Bool{
let fontPath = self.frameworkBundle().pathForResource(name, ofType: "ttf")!
let inData = NSData(contentsOfFile:fontPath)
var error: Unmanaged<CFError>?
let provider = CGDataProviderCreateWithCFData(inData)
if let font = CGFontCreateWithDataProvider(provider) {
CTFontManagerRegisterGraphicsFont(font, &error)
if error != nil {
print(error) //Or logged it
return false
}
}
return true
}
FrameworkBundleメソッド:
class func frameworkBundle() -> NSBundle{
var bundle = NSBundle()
var predicate = dispatch_once_t()
dispatch_once(&predicate) {
let mainBundlePath = NSBundle.mainBundle().bundlePath
let frameworkBundlePath = mainBundlePath.stringByAppendingString("/myFramework.framework/")
bundle = NSBundle(path: frameworkBundlePath)!
}
return bundle
}
呼び出しの例:(私の場合、すべてのフォントをFontsフォルダーに追加しました)
YouClassName.loadMyCustomFont("Fonts/Roboto-Regular")
訂正や発言は大歓迎です!
@ ALi-ABBASの回答のSwift3バージョンも、強制的にアンラップする代わりにアップラップオプションに更新されました。
fileprivate func loadCustomFont(name:String) -> Bool{
guard let fontPath = frameworkBundle.path(forResource: name, ofType: "ttf") else {
return false
}
guard let inData = NSData(contentsOfFile:fontPath) else {
return false
}
guard let provider = CGDataProvider(data: inData) else {
return false
}
let font = CGFont(provider)
var error: Unmanaged<CFError>?
CTFontManagerRegisterGraphicsFont(font, &error)
guard error == nil else {
print(error) //Or logged it
return false
}
return true
}