1、更换系统字体的方法
-
添加字体文件
-
使用苹果官方API动态下载
动态下载的优点:
1)不占用APP包的体积(字体文件下载到系统的目录中``/private/var/mobile/Library/Assets/com_apple_MobileAsset_Font/`)
2)不会有版权问题
3)下载以后无需再下载,而且应用之间共享(如果别的应用下载过该字体,你就不用下载了)
动态下载的缺点:
1)第一次下载会消耗一些流量和下载时间
2、如何动态下载字体?
2.1、查看字体postscript
1)打开mac自带字体册
2)
屏幕快照 2016-07-18 下午9.11.44.png
2.2、通过下面的方法判断系统是否存在该字体(fontName即为你要下载的字体的PostScript)
- (BOOL)isFontIsExist:(NSString *)fontName {
UIFont* font = [UIFont fontWithName:fontName size:12.0];
if (font && ([font.fontName compare:fontName] == NSOrderedSame
|| [font.familyName compare:fontName] == NSOrderedSame)) {
return YES;
} else {
return NO;
}
}
2.3、通过下面的方法下载字体
- (void)downloadWithfontName:(NSString *)fontName{
// 用字体的 PostScript 名字创建一个 Dictionary
NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithObjectsAndKeys:fontName, kCTFontNameAttribute, nil];
// 创建一个字体描述对象 CTFontDescriptorRef
CTFontDescriptorRef desc = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef)attrs);
// 将字体描述对象放到一个 NSMutableArray 中
NSMutableArray *descs = [NSMutableArray arrayWithCapacity:0];
[descs addObject:(__bridge id)desc];
CFRelease(desc);
__block BOOL errorDuringDownload = NO;
//匹配字体
CTFontDescriptorMatchFontDescriptorsWithProgressHandler( (__bridge CFArrayRef)descs, NULL, ^(CTFontDescriptorMatchingState state, CFDictionaryRef _Nonnull progressParameter) {
if (state == kCTFontDescriptorMatchingDidBegin) {//字体已经匹配
} else if (state == kCTFontDescriptorMatchingDidFinish) {//字体 %@ 下载完成
if (!errorDuringDownload) {
dispatch_async( dispatch_get_main_queue(), ^ {
// 可以在这里修改 UI 控件的字体
self.fontLabel.font = [UIFont fontWithName:self.fontArr[0] size:17];
self.boldfontlabel.font = [UIFont fontWithName:self.fontArr[1] size:17];
return ;
});
}
}
return (BOOL)YES;
});
//下载字体
CTFontDescriptorMatchFontDescriptorsWithProgressHandler( (__bridge CFArrayRef)descs, NULL, ^(CTFontDescriptorMatchingState state, CFDictionaryRef _Nonnull progressParameter) {
double progressValue = [[(__bridge NSDictionary *)progressParameter objectForKey:(id)kCTFontDescriptorMatchingPercentage] doubleValue];
if (state == kCTFontDescriptorMatchingWillBeginDownloading) {
NSLog(@" 字体开始下载 ");
} else if (state == kCTFontDescriptorMatchingDidFinishDownloading) {
NSLog(@" 字体下载完成 ");
dispatch_async( dispatch_get_main_queue(), ^ {
// 可以在这里修改 UI 控件的字体
self.fontLabel.font = [UIFont fontWithName:self.fontArr[0] size:17];
self.boldfontlabel.font = [UIFont fontWithName:self.fontArr[1] size:17];
});
} else if (state == kCTFontDescriptorMatchingDownloading) {
NSLog(@" 下载进度 %.0f%% ", progressValue);
} else if (state == kCTFontDescriptorMatchingDidFailWithError) {
NSError *error = [(__bridge NSDictionary *)progressParameter objectForKey:(id)kCTFontDescriptorMatchingError];
if (error != nil) {
_errorMessage = [error description];
} else {
_errorMessage = @"ERROR MESSAGE IS NOT AVAILABLE!";
}
// 设置标志
errorDuringDownload = YES;
NSLog(@" 下载错误: %@", _errorMessage);
}
return (BOOL)YES;
});
}
3、注意事项
1)网上现在很多资料写的都是以前的,坑的我好惨。
CTFontDescriptorMatchFontDescriptorsWithProgressHandler( (__bridge CFArrayRef)descs, NULL, ^(CTFontDescriptorMatchingState state, CFDictionaryRef progressParameter)
这个方法要改成下面的
CTFontDescriptorMatchFontDescriptorsWithProgressHandler((__bridge CFArrayRef)descs, NULL, ^bool(CTFontDescriptorMatchingState state, CFDictionaryRef _Nonnull progressParameter)
。否则真机、模拟器都可运行但是不能打包。
2)报错:incompatible block pointer types passing ‘BOOL(^)(CTFontDescriptorMatchingState,CFDictionaryRef)’ to parameter of type ‘CTFontDEscriptorProgressHandler _Nonnull’(aka ‘bool(^)(CTFontDescriptorMatchingState,CFDictionaryRef _Nonnull))
,解决办法同上。
3)2.2的方法都说是判断字体是否下载,但是通过我的实践,该方法其实是判断字体是是否Apple预装的Apple的字体详情,所以如果你的字体如果不在预装的列表里面,即使你下载了字体,程序也会走2.3的方法,但是它不会再重新执行下载的代码块,它只会走匹配的字体代码块。
网友评论