有没有一种方法可以知道 iOS 是否支持某个表情符号?

25

我正在开发一个iOS应用,其中表情符号在其中扮演着重要的角色。

在iOS 10.2中,发布了新的表情符号。

我很确定,例如如果有人使用的是iOS 8,他们实际上将无法看到这些表情符号。是否有方法来检测这个问题?我正在尝试动态构建所有受用户iOS版本支持的表情符号列表,但是我遇到了一些麻烦。


你是否正在尝试确定在您的应用程序中或您发送消息的对象中,用户是否可以使用表情符号?我想知道是否有表情符号的字符串表示形式。 - quantumpotato
@wajeeh 我可以为 iOS 10.2 生成表情符号,但这并不能告诉我某个表情符号是否在 iOS 9 中受支持。事实上,如果我能获得 iOS 9、9.1 等版本的表情符号列表,那就太好了 - iOS 10.2。目前我正在寻找这样的列表。 - David
啊,好的,请查看此链接http://en.stack.aiseen.org/questions/35687407/get-surrogate-pairs-from-an-emoji。另外,在我进行了一些测试后,我发现不支持的表情符号总是会回退到一个特定的字符(黑色问号),所以也许你可以从中受益。这个答案使用相同的方法:https://dev59.com/MJHea4cB1Zd3GeqPkRNz#39606543。 - Wajih
3
这是iOS 10.2新增表情符号的链接:http://emojipedia.org/apple/ios-10.2/new/。你可以向下滚动并选择其他iOS版本的更新日志。不确定该网站是否准确。这不是你要求的,但可能会有所帮助。 - Nikola Miljković
更新是一个完全不同的问题。请发表一个新请求。 - SwiftArchitect
显示剩余3条评论
2个回答

28

澄清:表情符号只是Unicode字符空间中的一个字符,因此现有解决方案适用于所有字符,而不仅仅是表情符号。

简介

要知道一个Unicode字符(包括表情符号)是否在给定的设备或操作系统上可用,请运行下面的unicodeAvailable()方法。

它通过将给定的字符图像与已知未定义的Unicode字符U+1FFF进行比较来实现。

Character扩展:unicodeAvailable()

private static let refUnicodeSize: CGFloat = 8
private static let refUnicodePng =
    Character("\u{1fff}").png(ofSize: Character.refUnicodeSize)

func unicodeAvailable() -> Bool {
    if let refUnicodePng = Character.refUnicodePng,
        let myPng = self.png(ofSize: Character.refUnicodeSize) {
        return refUnicodePng != myPng
    }
    return false
}

讨论

  1. 所有字符都将被渲染为 png,大小与以下定义一致:

    static let refUnicodeSize: CGFloat = 8

  2. 未定义的字符U+1FFF图像会在以下代码中计算一次:

    static let refUnicodePng = Character("\u{1fff}").png(ofSize: Character.refUnicodeSize)

  3. 一个辅助方法可以从Character可选地创建一个png:

    func png(ofSize fontSize: CGFloat) -> Data?

1. 例子:对三个表情符号进行测试

let codes:[Character] = ["\u{2764}","\u{1f600}","\u{1F544}"] // ❤️, , undefined
for unicode in codes {
    print("\(unicode) : \(unicode.unicodeAvailable())")
}

三个字符

2. 示例:测试一系列Unicode字符

func unicodeRange(from: Int, to: Int) {
    for unicodeNumeric in from...to {
        if let scalar = UnicodeScalar(unicodeNumeric) {
            let unicode = Character(scalar)
            let avail = unicode.unicodeAvailable()
            let hex = String(format: "0x%x", unicodeNumeric)
            print("\(unicode) \(hex) is \(avail ? "" : "not ")available")
        }
    }
}

几百个字符


助手函数:Characterpng

func png(ofSize fontSize: CGFloat) -> Data? {
    let attributes = [NSAttributedStringKey.font:
                          UIFont.systemFont(ofSize: fontSize)]
    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
}

► 您可以在 GitHub 上找到此解决方案,并在 Swift Recipes 上阅读详细介绍。


3
它只是尚未实现(或定义)的众多字符之一。因此,它会打印一个[?]问号,就像所有无效字符一样。所有无效Unicode字符共享相同的位图。 - SwiftArchitect
1
请注意,对于 ‍♂️(男子翻筋斗,U+1F938 U+200D U+2642 U+FE0F),此方法会失败,因为 PNG 将呈现为 [?]♂ 而不是 [?]。我通过仅呈现第一个代码点(使用 enumerateSubstringsInRange:options:usingBlock: 获得)来解决了这个问题。 - Ford
@Ford,可以在GitHub上找到通用解决方案。根据单元测试,无需呈现单个代码点。 - SwiftArchitect
@SwiftArchitect,这种方法无法处理国旗。例如,“NZ”编码为Unicode国家代码是可以的,但“EU”(某些软件坚持认为欧洲联盟是一个国家)返回的是被方框包围的字母E和U。我可以过滤掉我知道会引起问题的国家代码,但我仍然不知道macOS是否实际上为其余的创建了国旗字形。 - granada29
这种方法适用于欧盟。使用代码 U+1F1EA U+1F1EA 构建一个 Unicode Character,如 \u{1F1EA}\u{1F1EA},你将得到 ,并且单元测试 请参见 GitHub 项目 将通过。 - SwiftArchitect
这是一个很棒的解决方案@SwiftArchitect,谢谢分享!我尝试将其转换为适用于macOS应用程序的AppKit,但无法找到UIGraphicsBeginImageContext的合适等效项。您介意也分享一下macOS的解决方案吗? - ixany

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接