【问题标题】:How to convert CGFontRef to UIFont?如何将 CGFontRef 转换为 UIFont?
【发布时间】:2012-03-01 14:52:04
【问题描述】:

我想为UILabel 使用自定义字体。自定义字体由文件加载:

NSString *fontPath = ... ; // a TTF file in iPhone Documents folder
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithFilename([fontPath UTF8String]);
CGFontRef customFont = CGFontCreateWithDataProvider(fontDataProvider);
CGDataProviderRelease(fontDataProvider); 

如何将CGFontRef 转换为UIFont 以在[UILabel setFont:] 中使用?

【问题讨论】:

  • 您需要支持什么iOS版本?您可以通过编辑 Info.plist 将捆绑的字体加载为 UIFont 实例。
  • 我不确定将 CGFontRef 转换为 UIFont,但您可以创建一个采用 CGFontRef 的 UILabel 子类。检查此blog 进行操作
  • @Costique iOS 4.3 或更高版本是可以的。字体是用户下载应用后添加的,所以无法预设Info.plist。

标签: iphone ios uilabel uifont


【解决方案1】:

原则上,它们不能直接转换。一个简单的原因是 UIFont 封装了字体大小,而 CGFont 与大小无关(大小是图形上下文的属性;参见 CGContextSetFontSize())。

假设您已经确定了您想要的字体大小,您应该能够:

NSString *fontName = (NSString *)CGFontCopyFullName(someCGFontRef);
UIFont *font = [UIFont fontWithName:fontName size:someSize];
[fontName release];

我还没有实际测试过这个,但它应该可以工作(也许有一些小的补充)。我相信 CGFont 和 UIFont 的名称之间存在对应关系 - 但如果没有,这显然是行不通的。

【讨论】:

    【解决方案2】:

    您可以将您的 CGFont 转换为 CTFont,但不幸的是,这些都不会为您提供 UIFont。以下是获取 UIFont 的方法:请求系统字体,或通过 PostScript 名称请求字体。因此,对于 UILabel 中自定义提供的字体,我建议您使用后者。

    如果您提前知道您的应用将使用的字体文件,您可以将其添加到您的包中并使用 UIFont、+fontWithName:size: as UIFont 加载它在您的捆绑包中搜索具有该 PostScript 名称的字体文件。

    例如,TrueType 字体文件“VeraMono.ttf”的 PostScript 名称为“Bitstream Vera Sans Mono”,因此它被加载到 UILabel 中,如下所示:

    label.font = [UIFont fontWithName:@"Bitstream Vera Sans Mono" size:12];

    要以非动态方式获取 PostScript 名称,请使用字体工具,或者在上述情况下,PostScript 名称恰好等于 Finder > Get Info 显示的“全名”。

    但是,对于您不一定要提前知道字体的 PostScript 名称的情况(例如支持用户定义的字体),也许您可​​以将文件名加载到 NSData 中,并为其 PostScript 名称加载“grep”...

    祝你好运,

    【讨论】:

    • 感谢您的解释。 4 年后,您的回应以及 Josh Brown 的回答帮助了我!
    【解决方案3】:

    康拉德的答案很接近,但不太奏效。您需要为 UIFont 提供 PostScript 名称,而不是全名。

    NSString *fontName = (NSString *)CGFontCopyPostScriptName(fontRef);
    UIFont *font = [UIFont fontWithName:fontName size:someSize]
    

    【讨论】:

    • 请注意,CGFontCopyPostScriptName 分配并返回一个 CFStringRef,您必须稍后再使用 CFRelease。将返回值转换为 NSString 不利于可读性。
    【解决方案4】:

    您不能直接将CGFontRef转换为UIFont,但可以使用CTFontManagerRegisterGraphicsFont注册CGFontRef,然后创建对应的UIFont

    NSString* fpath = [documentsDirectory stringByAppendingPathComponent:@"custom_font_file_name.ttf"];
    CGDataProviderRef fontDataProvider = CGDataProviderCreateWithFilename([fpath UTF8String]);
    CGFontRef customFont = CGFontCreateWithDataProvider(fontDataProvider);
    CGDataProviderRelease(fontDataProvider);
    NSString *fontName = (__bridge NSString *)CGFontCopyFullName(customFont);
    CFErrorRef error;
    CTFontManagerRegisterGraphicsFont(customFont, &error);
    CGFontRelease(customFont);
    UIFont* uifont = [UIFont fontWithName:fontName size:12];
    

    【讨论】:

    • 我收到这个错误加载字体失败:操作无法完成。 (com.apple.coretext 错误 105 - 无法注册 CGFont '')
    • documentsDirectory.. "使用未声明的标识符'documentsDirectory'...你的意思是什么? .... ? ? ?
    【解决方案5】:

    为 Swift 4 更新以获取 PostScript 名称(其中font 是 CGFont):

    let fontName = font?.postScriptName as String?
    textLabel.font = UIFont(name: fontName!, size: 17)
    

    【讨论】:

      【解决方案6】:

      CTFontRefUIFonttoll-free bridged,因此您可以将 CGFont 转换为 CTFont,然后将其转换为 UIFont

      CTFontRef ctFont = CTFontCreateWithGraphicsFont(cgFont, pointSize, NULL, NULL);
      UIFont *uiFont = CFBridgingRelease(ctFont);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-06
        • 2014-11-20
        • 1970-01-01
        • 2014-08-18
        • 1970-01-01
        • 2020-05-19
        • 2012-04-04
        相关资源
        最近更新 更多