美文网首页iOSiOS DeveloperiOS 开发
iOS-动态下载所需的字体

iOS-动态下载所需的字体

作者: 上帝也是码农 | 来源:发表于2016-07-18 22:10 被阅读1217次

    1、更换系统字体的方法

    1. 添加字体文件

    2. 使用苹果官方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的方法,但是它不会再重新执行下载的代码块,它只会走匹配的字体代码块。

    Demo地址

    相关文章

      网友评论

      • 卓敦:后台接口返回的ttf文件,怎么使用呢
      • _Zero丶:下载完了,有办法删除么

      本文标题:iOS-动态下载所需的字体

      本文链接:https://www.haomeiwen.com/subject/mthmjttx.html