29

リソース(ペン先、画像、フォント)をパッケージ化するためのバンドルを使用してiOSフレームワークを作成していて、バンドルにカスタムフォントを埋め込もうとしていますが、フレームワークからロードできません。可能ですか?

1)これでフォントファイルをローカライズできます: objc NSString *fontPath = [[NSBundle frameworkBundle] pathForResource:@"MyCustomFont" ofType:@"ttf"]; 2)フォントリストに取得できません: objc NSArray * array = [UIFont familyNames]; バンドルのplistに「アプリケーションによって提供されるフォント」を含むフォント名を含めましたが、成功せず、 app info plist、成功せずにフレームワークリソースに含めます。

バンドルからペン先と画像をロードすることはできますが(バンドルの名前をプレフィックスとして付けることで)、フォントについてはロードできません。何か考えはありますか?

編集:私は次の投稿を見ました:iPhoneアプリケーションにカスタムフォントを埋め込むことはできますか?、しかし質問は「iPhoneアプリケーションにカスタムフォントを埋め込むことはできますか?」です。「外部フレームワーク/バンドルにカスタムフォントを埋め込むことはできますか?」ではありません。また、興味深い動的ローディングへの参照も作成しますが、フレームワークに使用できないソリューションであるプライベートAPIを使用しています。

ありがとう

4

7 に答える 7

22

スウィフト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)
}
于 2016-11-22T18:47:08.340 に答える
21

これは、Info.plistにフォントを配置せずにフォントを動的にロードできる新しい方法です:http://www.marco.org/2012/12/21/ios-dynamic-font-loading

于 2013-03-19T20:56:10.460 に答える
17

これが、「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をプロジェクトに統合する必要があります

于 2013-03-20T10:35:11.260 に答える
4

迅速に、私は以下のコードを使用します:

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")

あなたの訂正と発言は大歓迎です!

于 2015-10-16T16:53:21.853 に答える
1

Swift 4/5用に更新され、ブール値を返す代わりにエラーをスローするように変更されました。

enum FontLoadingError: Error {
    case fileNotFound
    case unreadableFontData
}

func loadCustomFont(name: String) throws {
    guard let fontURL = frameworkBundle.url(forResource: name, withExtension: "ttf") else {
        throw FontLoadingError.fileNotFound
    }

    guard
        let provider = CGDataProvider(url: fontURL as CFURL),
        let font = CGFont(provider)
    else {
        throw FontLoadingError.unreadableFontData
    }

    var cfError: Unmanaged<CFError>?
    CTFontManagerRegisterGraphicsFont(font, &cfError)

    if let error = cfError as? Error {
        throw error
    }
}
于 2020-06-18T13:48:36.887 に答える
1

ファイル/バンドルにフォントがある場合は、この拡張機能を使用できます。

public extension UIFont {

    static func register(from url: URL) throws {
        if !FileManager.default.fileExists(atPath: url.path) {
            throw VError.incorrectFont
        }

        var error: Unmanaged<CFError>?

        guard CTFontManagerRegisterFontsForURL(url as CFURL, .process, &error) else {
            throw error!.takeUnretainedValue()
        }
    }
}
于 2020-11-16T15:18:23.647 に答える
0

@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
}
于 2017-03-17T18:05:20.097 に答える