Ответ 1
Это новый метод, который позволяет загружать шрифты динамически, не помещая их в ваш Info.plist: http://www.marco.org/2012/12/21/ios-dynamic-font-loading
Я создаю инфраструктуру ios с ее пакетом для упаковки ресурсов (nib, images, fonts), и я пытаюсь внедрить собственный шрифт в комплекте, но я не могу загрузить его из фреймворка, возможно ли это?
1) Я могу локализовать файл шрифта следующим образом:
objc
NSString *fontPath = [[NSBundle frameworkBundle] pathForResource:@"MyCustomFont" ofType:@"ttf"];
2) Но я не могу получить его в своих списках шрифтов:
objc
NSArray * array = [UIFont familyNames];
Я включил свое имя шрифта в plest plist с "Шрифтами, предоставленными приложением", без успеха, также попробовал и в Info Info Plist, включив его в рамки ressource без успеха.
Я могу загрузить nib и изображения из пакета (путем префикса с именем пакета), но не для шрифта. Любая мысль?
EDIT: Я увидел следующее сообщение: Могу ли я встроить собственный шрифт в iPhone-приложение?, но вопрос просто "Могу ли я встроить собственный шрифт в приложение для iPhone?" а не "Могу ли я встроить собственный шрифт во внешнюю структуру/пакет?" Он также делает ссылки на динамическую загрузку, которая интересна, но использует частный api, который не является подходящим решением для фреймворка.
Спасибо
Это новый метод, который позволяет загружать шрифты динамически, не помещая их в ваш Info.plist: http://www.marco.org/2012/12/21/ios-dynamic-font-loading
Вот как я это сделал для моего fmk на основе решения, предоставленного "Дэвидом М.", Это решение не требует добавления ссылки на шрифт в plist.
1) Класс, загружающий шрифт
- (void) loadMyCustomFont{
NSString *fontPath = [[NSBundle frameworkBundle] pathForResource:@"MyFont" 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 в ваш проект
Swift 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)
}
В быстром, я использую следующий код:
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")
Ваши исправления и замечания приветствуются!
Swift 3 версия ответа @Ali-ABBAS, также обновленная до вариантов обертывания вместо развертывания силы.
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
}