我已經看到這個問題並且回答了很多次,但我還沒有看到真正的答案。 常見的「解決方案」是:如何在iOS下動態加載字體。 (真實的)
- 字體添加到應用程序包,並在Info.plist文件註冊。
- 使用自定義字體解析和渲染庫(如Zynga的FontLabel)。
- 這是無法完成的。
所以,問題是:如何動態負荷的iOS下的字體? 加載字體「動態」是指加載應用程序編譯時未知的任何給定字體。
我已經看到這個問題並且回答了很多次,但我還沒有看到真正的答案。 常見的「解決方案」是:如何在iOS下動態加載字體。 (真實的)
所以,問題是:如何動態負荷的iOS下的字體? 加載字體「動態」是指加載應用程序編譯時未知的任何給定字體。
字體可以很容易地從任何位置或任何字節流動態加載。看到這裏的文章:http://www.marco.org/2012/12/21/ios-dynamic-font-loading
NSData *inData = /* your font-file data */;
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);
}
CFRelease(font);
CFRelease(provider);
是否可以指定名稱來註冊加載時的字體? – user102008
@ user102008這似乎不可能。 –
@ user102008 *獲取* CGFontRef'對象的名稱,而不是'CGFontCopyFullName'。 – adib
大時間最近的文章從馬可·題爲Loading iOS fonts dynamically。
NSData *inData = /* your decrypted font-file data */;
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);
}
CFRelease(font);
CFRelease(provider);
這是一個非常有趣的情況。我發現了Marco的帖子,併發布了相同的代碼,作爲對SO上一堆問題的答案。但後來我認爲創建一個自我回答的問題可能會更好,以便更容易發現答案。然後主持人刪除了我自己的答案,用我自己的問題用同樣的代碼=( –
是否可以指定名稱來註冊字體,因爲加載時? – user102008
您需要'#import
// Note : add "CoreText.framework" into your project to support following code
// Put loadCustomFont function inside app delegate or any shared class to access any where in code...
-(void)loadCustomFont:(NSMutableArray *)customFontFilePaths{
for(NSString *fontFilePath in customFontFilePaths){
if([[NSFileManager defaultManager] fileExistsAtPath:fontFilePath]){
NSData *inData = [NSData dataWithContentsOfFile:fontFilePath];
CFErrorRef error;
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)inData);
CGFontRef font = CGFontCreateWithDataProvider(provider);
// NSString *fontName = (__bridge NSString *)CGFontCopyFullName(font);
if (!CTFontManagerRegisterGraphicsFont(font, &error)) {
CFStringRef errorDescription = CFErrorCopyDescription(error);
NSLog(@"Failed to load font: %@", errorDescription);
CFRelease(errorDescription);
}
CFRelease(font);
CFRelease(provider);
}
}
}
// Use as follow inside your view controller...
- (void)viewDidLoad
{
[super viewDidLoad];
// pass all font files name into array which you want to load dynamically...
NSMutableArray *customFontsPath = [[NSMutableArray alloc] init];
NSArray *fontFileNameArray = [NSArray arrayWithObjects:@"elbow_v001.ttf",@"GothamRnd-MedItal.otf", nil];
for(NSString *fontFileName in fontFileNameArray){
NSString *fileName = [fontFileName stringByDeletingPathExtension];
NSString *fileExtension = [fontFileName pathExtension];
[customFontsPath addObject:[[NSBundle mainBundle] pathForResource:fileName ofType:fileExtension]];
}
AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate];
// load custom font into memory...
[appDel loadCustomFont:customFontsPath];
// Use font as below
[lblName setFont:[UIFont fontWithName:@"Elbow v100" size:15.0]];
[lblName2 setFont:[UIFont fontWithName:@"Gotham Rounded" size:20.0]];
}
如果你要這樣做,爲什麼不使用'CTFontManagerRegisterFontsForURL()'? – user102008
@ user102008,因爲你無法知道你從那個URL註冊的字體是什麼。通過'CGFontRef'去使你能夠獲得然後使用普通的'UIFont'方法。 – adib
如果應用程序掛起,請使用以下命令:http://stackoverflow.com/questions/24900979/cgfontcreatewithdataprovider-hangs-in-airplane-mode – pegpeg
這裏迅速版本:
let inData: NSData = /* your font-file data */;
let error: UnsafeMutablePointer<Unmanaged<CFError>?> = nil
let provider = CGDataProviderCreateWithCFData(inData)
if let font = CGFontCreateWithDataProvider(provider) {
if (!CTFontManagerRegisterGraphicsFont(font, error)) {
if let unmanagedError = error.memory {
let errorDescription = CFErrorCopyDescription(unmanagedError.takeUnretainedValue())
NSLog("Failed to load font: \(errorDescription)");
}
}
}
下載從服務器TTF文件?
如果您正在下載一個TTF文件,那麼你可以做以下與iOS字體管理器來註冊您的自定義字體,這段代碼也需要照顧TTF文件的更新(字體更新):
+(void)registerFontsAtPath:(NSString *)ttfFilePath
{
NSFileManager * fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:ttfFilePath] == YES)
{
[UIFont familyNames];//This is here for a bug where font registration API hangs for forever.
//In case of TTF file update : Fonts are already registered, first de-register them from Font Manager
CFErrorRef cfDe_RegisterError;
bool fontsDeregistered = CTFontManagerUnregisterFontsForURL((__bridge CFURLRef)[NSURL fileURLWithPath:ttfFilePath], kCTFontManagerScopeNone, &cfDe_RegisterError);
//finally register the fonts with Font Manager,
CFErrorRef cfRegisterError;
bool fontsRegistered= CTFontManagerRegisterFontsForURL((__bridge CFURLRef)[NSURL fileURLWithPath:ttfFilePath], kCTFontManagerScopeNone, &cfRegisterError);
}
這裏是@ mt81爲斯威夫特3更新的答案:
guard
let path = "Path to some font file",
let fontFile = NSData(contentsOfFile: path)
else {
print "Font file not found?"
}
guard let provider = CGDataProvider(data: fontFile)
else {
print "Failed to create DataProvider"
}
let font = CGFont(provider)
let error: UnsafeMutablePointer<Unmanaged<CFError>?>? = nil
guard CTFontManagerRegisterGraphicsFont(font, error) else {
guard
let unError = error?.pointee?.takeUnretainedValue(),
let description = CFErrorCopyDescription(unError)
else {
print "Unknown error"
}
print description
}
看着'CTFontManagerCreateFontDescriptorsFromURL'? – Bejmax
請參閱http://stackoverflow.com/a/12497630/724514。只是試了一下,並能夠加載和使用字體。爲了「加載應用程序編譯時未知的任何給定字體」,您可以下載字體並將其保存在Documents目錄中,然後按照代碼中的示例進行操作。 – bobnoble