检测无法正确显示unicode字符的时间

时间:2015-07-12 00:31:25

标签: ios swift unicode watchkit

某些unicode字符无法在iOS上显示,但在OS X上正确显示。同样,iOS可以显示的某些unicode字符无法在watchOS上显示。这是因为这些平台上安装了不同的内置字体。

当一个角色无法显示时 - 例如,它显示为?在一个盒子里面,如下:
enter image description here

我也看到一些角色显示为外星人 - 不知道为什么差异:
enter image description here

有没有办法知道在给定一个unicode字符的字符串(例如""

)的情况下,何时无法正确显示特定的unicode字符

请注意,该解决方案需要适用于iOS和watchOS 2。

2 个答案:

答案 0 :(得分:4)

您可以使用CTFontGetGlyphsForCharacters()来确定字体是否具有特定代码点的字形(请注意,需要将补充字符作为代理对进行检查):

CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica"), 12, NULL);
const UniChar code_point[] = { 0xD83C, 0xDCA1 };  // U+1F0A1
CGGlyph glyph[] = { 0, 0 };
bool has_glyph = CTFontGetGlyphsForCharacters(font, code_point, glyph, 2);

或者,在Swift中:

let font = CTFontCreateWithName("Helvetica", 12, nil)
var code_point: [UniChar] = [0xD83C, 0xDCA1]
var glyphs: [CGGlyph] = [0, 0]
let has_glyph = CTFontGetGlyphsForCharacters(font, &code_point, &glyph, 2)

如果要检查系统将尝试从中加载字形的完整回退字体集,则需要检查CTFontCopyDefaultCascadeListForLanguages()返回的所有字体。检查answer to this question以获取有关如何创建回退字体列表的信息。

答案 1 :(得分:0)

与已知的未定义角色U+1FFF进行比较:

/// - Parameter font: a UIFont
/// - Returns: true if glyph exists
func glyphAvailable(forFont font:UIFont) -> Bool {
    if let refUnicodePng = Character("\u{1fff}").png(forFont: font),
        let myPng = self.png(forFont: font) {
        return refUnicodePng != myPng
    }
    return false
}

使用 png 位图:

/// - Parameter font: a UIFont
/// - Returns: an optional png representation
func png(forFont font: UIFont) -> Data? {
    let attributes = [NSAttributedStringKey.font: font]
    let charStr = "\(self)" as NSString
    let size = charStr.size(withAttributes: attributes)

    UIGraphicsBeginImageContext(size)
    charStr.draw(at: CGPoint(x: 0,y :0), withAttributes: attributes)

    var png:Data? = nil
    if let charImage = UIGraphicsGetImageFromCurrentImageContext() {
        png = UIImagePNGRepresentation(charImage)
    }

    UIGraphicsEndImageContext()
    return png
}

已回答here