我正在创建一个带有包的ios 框架,用于打包资源(笔尖,图片,字体),我试图嵌入<捆绑中的strong>自定义字体,但我无法从框架中加载它,是否可能?
1)我可以用这个本地化字体文件:
objc
NSString *fontPath = [[NSBundle frameworkBundle] pathForResource:@"MyCustomFont" ofType:@"ttf"];
2)但我无法在我的字体列表中获取它:
objc
NSArray * array = [UIFont familyNames];
我将我的字体名称包含在捆绑包的plist中,其中包含应用程序&#34;提供的&#34;字体,但没有成功,也尝试在app info plist中,将其包含在框架资源中但没有成功。
我可以从包中加载nib和图像(通过使用包的名称加前缀)但不能加载字体。有什么想法?
编辑:我看到以下帖子:Can I embed a custom font in an iPhone application?,但问题只是&#34;我可以在iPhone应用程序中嵌入自定义字体吗?&#34;不是&#34;我可以在外部框架/捆绑中嵌入自定义字体吗?&#34;它还引用了一个有趣的动态加载,但它使用的是私有api,这对于框架来说不是可用的解决方案。
由于
答案 0 :(得分:18)
这是一种新方法,可让您动态加载字体,而无需将其放入Info.plist中:http://www.marco.org/2012/12/21/ios-dynamic-font-loading
答案 1 :(得分:17)
这是基于“David M.”提供的解决方案为我的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
答案 2 :(得分:12)
斯威夫特3:
首先,不要使用追加路径组件从main访问框架包...从其标识符实例化它。您可以获得如下字体网址:
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)
}
答案 3 :(得分:4)
在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
}
电话的例子:(在我的情况下,我在字体文件夹中添加了所有字体)
YouClassName.loadMyCustomFont("Fonts/Roboto-Regular")
欢迎您提出更正和评论!
答案 4 :(得分: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
}
}
答案 5 :(得分: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()
}
}
}
答案 6 :(得分:0)
@Ali-ABBAS的答案的Swift 3版本,也更新为up-wrap选项而不是强制解包。
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
}