2015-07-12 113 views
4

某些unicode字符無法在iOS上顯示,但在OS X上正確顯示。同樣,iOS可顯示的某些unicode字符無法顯示在watchOS上。這是由於這些平臺上安裝了不同的內置字體。當unicode字符無法正確顯示時檢測到

當一個角色無法顯示 - 例如,它顯示爲?在一個盒子裏,像這樣:
enter image description here

我也看到了一些字符顯示爲外星人而不是 - 不知道爲什麼區別:
enter image description here

有沒有辦法知道,當一個特定的Unicode字符將無法正確顯示給定的Unicode字符的字符串,如""

請注意,該解決方案需要兩個iOS的工作,watchOS 2.

+1

也許使用'CTFontGetGlyphsForCharacters(...)'? – MirekE

+0

你可以給我們這兩個代碼點嗎? –

+0

@ZoffDino我沒有一個外國人傢伙得心應手,但是以?爲例,這個角色顯示爲?在iOS上: – Joey

回答

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); 

或者,在斯威夫特:

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) 

如果要查看完整的一套TH後備字體的系統會嘗試加載字形,您需要檢查CTFontCopyDefaultCascadeListForLanguages()返回的所有字體。查看answer to this question以獲取有關如何創建備用字體列表的信息。

+0

has_glyph是false,那麼不可能顯示正確嗎? – NSDeveloper

+0

如果'has_glyph == false',它將使用帶有框或問號的最後度假村字體(如原始問題)進行渲染。 –

+0

非常整齊!有沒有一種更有效的方法來知道,如果任何字體可以顯示給定的字形,而無需在所有從所述方法返回的字體的循環中運行該代碼?我想這對於大量的字形來說效率很低。 – Joey

0

比較針對已知,未定義的字符U+1FFF:使用PNG位圖

/// - 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 
} 

/// - 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